From 257ab844d53d4d71a8345c3e0501a5dd2082e951 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:24:27 +0000 Subject: [PATCH 01/11] SDK regeneration --- .fern/metadata.json | 7 +- pyproject.toml | 2 +- .../v1/settings/think/models/raw_client.py | 10 +- .../v1/types/agent_v1agent_audio_done.py | 5 +- .../types/agent_v1agent_started_speaking.py | 5 +- .../agent/v1/types/agent_v1agent_thinking.py | 5 +- .../v1/types/agent_v1conversation_text.py | 5 +- src/deepgram/agent/v1/types/agent_v1error.py | 5 +- .../v1/types/agent_v1function_call_request.py | 5 +- ..._v1function_call_request_functions_item.py | 5 +- .../v1/types/agent_v1inject_agent_message.py | 5 +- .../v1/types/agent_v1inject_user_message.py | 5 +- .../v1/types/agent_v1injection_refused.py | 5 +- .../agent/v1/types/agent_v1keep_alive.py | 5 +- .../agent/v1/types/agent_v1prompt_updated.py | 5 +- .../agent_v1receive_function_call_response.py | 5 +- .../agent_v1send_function_call_response.py | 5 +- .../agent/v1/types/agent_v1settings.py | 5 +- .../agent/v1/types/agent_v1settings_agent.py | 5 +- .../types/agent_v1settings_agent_context.py | 5 +- ...ngs_agent_context_messages_item_content.py | 5 +- ...nt_context_messages_item_function_calls.py | 5 +- ...item_function_calls_function_calls_item.py | 5 +- .../v1/types/agent_v1settings_agent_listen.py | 5 +- .../agent_v1settings_agent_listen_provider.py | 9 +- ...ent_v1settings_agent_listen_provider_v1.py | 5 +- ...ent_v1settings_agent_listen_provider_v2.py | 5 +- .../v1/types/agent_v1settings_applied.py | 5 +- .../agent/v1/types/agent_v1settings_audio.py | 5 +- .../v1/types/agent_v1settings_audio_input.py | 5 +- .../v1/types/agent_v1settings_audio_output.py | 5 +- .../agent/v1/types/agent_v1settings_flags.py | 5 +- .../agent/v1/types/agent_v1speak_updated.py | 5 +- .../agent/v1/types/agent_v1update_prompt.py | 5 +- .../agent/v1/types/agent_v1update_speak.py | 5 +- .../v1/types/agent_v1user_started_speaking.py | 5 +- .../agent/v1/types/agent_v1warning.py | 5 +- .../agent/v1/types/agent_v1welcome.py | 5 +- src/deepgram/auth/v1/tokens/raw_client.py | 10 +- src/deepgram/core/__init__.py | 7 + src/deepgram/core/client_wrapper.py | 3 +- src/deepgram/core/unchecked_base_model.py | 376 +++++++++++++ src/deepgram/listen/v1/client.py | 28 +- src/deepgram/listen/v1/media/raw_client.py | 18 +- .../listen/v1/types/listen_v1close_stream.py | 5 +- .../listen/v1/types/listen_v1finalize.py | 5 +- .../listen/v1/types/listen_v1keep_alive.py | 5 +- .../listen/v1/types/listen_v1metadata.py | 5 +- .../listen/v1/types/listen_v1results.py | 5 +- .../v1/types/listen_v1results_channel.py | 5 +- ...ten_v1results_channel_alternatives_item.py | 5 +- ...ts_channel_alternatives_item_words_item.py | 5 +- .../types/listen_v1results_entities_item.py | 5 +- .../v1/types/listen_v1results_metadata.py | 5 +- .../listen_v1results_metadata_model_info.py | 5 +- .../v1/types/listen_v1speech_started.py | 5 +- .../listen/v1/types/listen_v1utterance_end.py | 5 +- src/deepgram/listen/v2/client.py | 20 +- .../listen/v2/types/listen_v2close_stream.py | 5 +- .../listen/v2/types/listen_v2connected.py | 5 +- .../listen/v2/types/listen_v2fatal_error.py | 5 +- .../listen/v2/types/listen_v2turn_info.py | 5 +- .../v2/types/listen_v2turn_info_words_item.py | 5 +- src/deepgram/manage/v1/models/raw_client.py | 18 +- .../projects/billing/balances/raw_client.py | 18 +- .../projects/billing/breakdown/raw_client.py | 10 +- .../v1/projects/billing/fields/raw_client.py | 10 +- .../projects/billing/purchases/raw_client.py | 10 +- .../manage/v1/projects/keys/raw_client.py | 34 +- .../v1/projects/members/invites/raw_client.py | 26 +- .../manage/v1/projects/members/raw_client.py | 18 +- .../v1/projects/members/scopes/raw_client.py | 18 +- .../manage/v1/projects/models/raw_client.py | 18 +- src/deepgram/manage/v1/projects/raw_client.py | 42 +- .../manage/v1/projects/requests/raw_client.py | 18 +- .../v1/projects/usage/breakdown/raw_client.py | 10 +- .../v1/projects/usage/fields/raw_client.py | 10 +- .../manage/v1/projects/usage/raw_client.py | 10 +- src/deepgram/read/v1/text/raw_client.py | 10 +- .../v1/distribution_credentials/raw_client.py | 34 +- src/deepgram/speak/v1/audio/raw_client.py | 6 +- src/deepgram/speak/v1/types/speak_v1clear.py | 5 +- .../speak/v1/types/speak_v1cleared.py | 5 +- src/deepgram/speak/v1/types/speak_v1close.py | 5 +- src/deepgram/speak/v1/types/speak_v1flush.py | 5 +- .../speak/v1/types/speak_v1flushed.py | 5 +- .../speak/v1/types/speak_v1metadata.py | 5 +- src/deepgram/speak/v1/types/speak_v1text.py | 5 +- .../speak/v1/types/speak_v1warning.py | 5 +- .../types/agent_think_models_v1response.py | 5 +- ..._think_models_v1response_models_item_id.py | 5 +- ...think_models_v1response_models_item_one.py | 5 +- ...ink_models_v1response_models_item_three.py | 5 +- ...think_models_v1response_models_item_two.py | 5 +- ...hink_models_v1response_models_item_zero.py | 5 +- src/deepgram/types/anthropic.py | 5 +- .../types/aws_bedrock_think_provider.py | 5 +- .../aws_bedrock_think_provider_credentials.py | 5 +- .../types/aws_polly_speak_provider.py | 5 +- .../aws_polly_speak_provider_credentials.py | 5 +- .../types/billing_breakdown_v1response.py | 5 +- ...billing_breakdown_v1response_resolution.py | 5 +- ...lling_breakdown_v1response_results_item.py | 5 +- ...akdown_v1response_results_item_grouping.py | 5 +- src/deepgram/types/cartesia.py | 5 +- .../types/cartesia_speak_provider_voice.py | 5 +- src/deepgram/types/create_key_v1response.py | 5 +- ...ect_distribution_credentials_v1response.py | 5 +- ...als_v1response_distribution_credentials.py | 5 +- ...tribution_credentials_v1response_member.py | 5 +- .../types/create_project_invite_v1response.py | 5 +- src/deepgram/types/deepgram.py | 5 +- .../types/delete_project_invite_v1response.py | 5 +- .../types/delete_project_key_v1response.py | 5 +- .../types/delete_project_member_v1response.py | 5 +- .../types/delete_project_v1response.py | 5 +- .../types/eleven_labs_speak_provider.py | 5 +- .../types/error_response_legacy_error.py | 5 +- .../types/error_response_modern_error.py | 5 +- .../types/get_model_v1response_batch.py | 5 +- .../types/get_model_v1response_metadata.py | 5 +- .../get_model_v1response_metadata_metadata.py | 5 +- .../types/get_project_balance_v1response.py | 5 +- ...ect_distribution_credentials_v1response.py | 5 +- ...als_v1response_distribution_credentials.py | 5 +- ...tribution_credentials_v1response_member.py | 5 +- .../types/get_project_key_v1response.py | 5 +- .../types/get_project_key_v1response_item.py | 5 +- .../get_project_key_v1response_item_member.py | 5 +- ...ject_key_v1response_item_member_api_key.py | 5 +- .../types/get_project_request_v1response.py | 5 +- src/deepgram/types/get_project_v1response.py | 5 +- src/deepgram/types/google.py | 5 +- src/deepgram/types/grant_v1response.py | 5 +- src/deepgram/types/groq.py | 5 +- .../types/leave_project_v1response.py | 5 +- .../types/list_billing_fields_v1response.py | 5 +- src/deepgram/types/list_models_v1response.py | 5 +- .../list_models_v1response_stt_models.py | 5 +- .../list_models_v1response_tts_models.py | 5 +- ...t_models_v1response_tts_models_metadata.py | 5 +- .../types/list_project_balances_v1response.py | 5 +- ...oject_balances_v1response_balances_item.py | 5 +- ...ect_distribution_credentials_v1response.py | 5 +- ...1response_distribution_credentials_item.py | 5 +- ...edentials_item_distribution_credentials.py | 5 +- ...se_distribution_credentials_item_member.py | 5 +- .../types/list_project_invites_v1response.py | 5 +- ...project_invites_v1response_invites_item.py | 5 +- .../types/list_project_keys_v1response.py | 5 +- ...t_project_keys_v1response_api_keys_item.py | 5 +- ...t_keys_v1response_api_keys_item_api_key.py | 5 +- ...ct_keys_v1response_api_keys_item_member.py | 5 +- .../list_project_member_scopes_v1response.py | 5 +- .../types/list_project_members_v1response.py | 5 +- ...project_members_v1response_members_item.py | 5 +- .../list_project_purchases_v1response.py | 5 +- ...roject_purchases_v1response_orders_item.py | 5 +- .../types/list_project_requests_v1response.py | 5 +- .../types/list_projects_v1response.py | 5 +- .../list_projects_v1response_projects_item.py | 5 +- .../types/listen_v1accepted_response.py | 5 +- src/deepgram/types/listen_v1redact.py | 8 +- src/deepgram/types/listen_v1response.py | 5 +- .../types/listen_v1response_metadata.py | 5 +- ...listen_v1response_metadata_intents_info.py | 5 +- ...sten_v1response_metadata_sentiment_info.py | 5 +- ...listen_v1response_metadata_summary_info.py | 5 +- .../listen_v1response_metadata_topics_info.py | 5 +- .../types/listen_v1response_results.py | 5 +- ...listen_v1response_results_channels_item.py | 5 +- ...results_channels_item_alternatives_item.py | 5 +- ...ls_item_alternatives_item_entities_item.py | 5 +- ...nnels_item_alternatives_item_paragraphs.py | 5 +- ...natives_item_paragraphs_paragraphs_item.py | 9 +- ...ragraphs_paragraphs_item_sentences_item.py | 5 +- ...s_item_alternatives_item_summaries_item.py | 5 +- ...nels_item_alternatives_item_topics_item.py | 5 +- ...nnels_item_alternatives_item_words_item.py | 5 +- ...ponse_results_channels_item_search_item.py | 5 +- ...lts_channels_item_search_item_hits_item.py | 5 +- .../listen_v1response_results_summary.py | 5 +- ...sten_v1response_results_utterances_item.py | 9 +- ...onse_results_utterances_item_words_item.py | 7 +- src/deepgram/types/open_ai_speak_provider.py | 5 +- src/deepgram/types/open_ai_think_provider.py | 5 +- .../types/project_request_response.py | 5 +- src/deepgram/types/read_v1request_text.py | 5 +- src/deepgram/types/read_v1request_url.py | 5 +- src/deepgram/types/read_v1response.py | 5 +- .../types/read_v1response_metadata.py | 5 +- .../read_v1response_metadata_metadata.py | 5 +- ...response_metadata_metadata_intents_info.py | 5 +- ...sponse_metadata_metadata_sentiment_info.py | 5 +- ...response_metadata_metadata_summary_info.py | 5 +- ...1response_metadata_metadata_topics_info.py | 5 +- src/deepgram/types/read_v1response_results.py | 5 +- .../types/read_v1response_results_summary.py | 5 +- ...read_v1response_results_summary_results.py | 5 +- ...esponse_results_summary_results_summary.py | 5 +- src/deepgram/types/shared_intents.py | 5 +- src/deepgram/types/shared_intents_results.py | 5 +- .../types/shared_intents_results_intents.py | 5 +- ...d_intents_results_intents_segments_item.py | 5 +- ...ults_intents_segments_item_intents_item.py | 5 +- src/deepgram/types/shared_sentiments.py | 5 +- .../types/shared_sentiments_average.py | 5 +- .../types/shared_sentiments_segments_item.py | 5 +- src/deepgram/types/shared_topics.py | 5 +- src/deepgram/types/shared_topics_results.py | 5 +- .../types/shared_topics_results_topics.py | 5 +- ...red_topics_results_topics_segments_item.py | 5 +- ...esults_topics_segments_item_topics_item.py | 5 +- src/deepgram/types/speak_settings_v1.py | 5 +- .../types/speak_settings_v1endpoint.py | 5 +- .../types/speak_settings_v1provider.py | 15 +- src/deepgram/types/think_settings_v1.py | 5 +- .../types/think_settings_v1endpoint.py | 5 +- .../types/think_settings_v1functions_item.py | 5 +- ...hink_settings_v1functions_item_endpoint.py | 5 +- .../types/think_settings_v1provider.py | 15 +- ...update_project_member_scopes_v1response.py | 5 +- .../types/update_project_v1response.py | 5 +- .../types/usage_breakdown_v1response.py | 5 +- .../usage_breakdown_v1response_resolution.py | 5 +- ...usage_breakdown_v1response_results_item.py | 5 +- ...akdown_v1response_results_item_grouping.py | 5 +- src/deepgram/types/usage_fields_v1response.py | 5 +- .../usage_fields_v1response_models_item.py | 5 +- src/deepgram/types/usage_v1response.py | 5 +- .../types/usage_v1response_resolution.py | 5 +- tests/custom/test_text_builder.py | 500 ------------------ tests/custom/test_transport.py | 481 ----------------- 233 files changed, 1216 insertions(+), 1618 deletions(-) create mode 100644 src/deepgram/core/unchecked_base_model.py delete mode 100644 tests/custom/test_text_builder.py delete mode 100644 tests/custom/test_transport.py diff --git a/.fern/metadata.json b/.fern/metadata.json index 34452365..8eb0bbad 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -11,7 +11,10 @@ }, "use_typeddict_requests": true, "should_generate_websocket_clients": true, - "enable_wire_tests": true + "enable_wire_tests": true, + "pydantic_config": { + "skip_validation": true + } }, - "sdkVersion": "6.0.0-beta.4" + "sdkVersion": "0.0.333" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b4940270..3a0beb7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "deepgram-sdk" -version = "6.0.0" +version = "0.0.333" description = "" readme = "README.md" authors = [] diff --git a/src/deepgram/agent/v1/settings/think/models/raw_client.py b/src/deepgram/agent/v1/settings/think/models/raw_client.py index a48447d8..968ef5cf 100644 --- a/src/deepgram/agent/v1/settings/think/models/raw_client.py +++ b/src/deepgram/agent/v1/settings/think/models/raw_client.py @@ -6,8 +6,8 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.agent_think_models_v1response import AgentThinkModelsV1Response @@ -42,7 +42,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( AgentThinkModelsV1Response, - parse_obj_as( + construct_type( type_=AgentThinkModelsV1Response, # type: ignore object_=_response.json(), ), @@ -53,7 +53,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -95,7 +95,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( AgentThinkModelsV1Response, - parse_obj_as( + construct_type( type_=AgentThinkModelsV1Response, # type: ignore object_=_response.json(), ), @@ -106,7 +106,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/agent/v1/types/agent_v1agent_audio_done.py b/src/deepgram/agent/v1/types/agent_v1agent_audio_done.py index 95f3f376..a8d9fddd 100644 --- a/src/deepgram/agent/v1/types/agent_v1agent_audio_done.py +++ b/src/deepgram/agent/v1/types/agent_v1agent_audio_done.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1AgentAudioDone(UniversalBaseModel): +class AgentV1AgentAudioDone(UncheckedBaseModel): type: typing.Literal["AgentAudioDone"] = pydantic.Field(default="AgentAudioDone") """ Message type identifier indicating the agent has finished sending audio diff --git a/src/deepgram/agent/v1/types/agent_v1agent_started_speaking.py b/src/deepgram/agent/v1/types/agent_v1agent_started_speaking.py index e6c47c6f..ba913bf5 100644 --- a/src/deepgram/agent/v1/types/agent_v1agent_started_speaking.py +++ b/src/deepgram/agent/v1/types/agent_v1agent_started_speaking.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1AgentStartedSpeaking(UniversalBaseModel): +class AgentV1AgentStartedSpeaking(UncheckedBaseModel): type: typing.Literal["AgentStartedSpeaking"] = pydantic.Field(default="AgentStartedSpeaking") """ Message type identifier for agent started speaking diff --git a/src/deepgram/agent/v1/types/agent_v1agent_thinking.py b/src/deepgram/agent/v1/types/agent_v1agent_thinking.py index 4b63c92f..7c3e6531 100644 --- a/src/deepgram/agent/v1/types/agent_v1agent_thinking.py +++ b/src/deepgram/agent/v1/types/agent_v1agent_thinking.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1AgentThinking(UniversalBaseModel): +class AgentV1AgentThinking(UncheckedBaseModel): type: typing.Literal["AgentThinking"] = pydantic.Field(default="AgentThinking") """ Message type identifier for agent thinking diff --git a/src/deepgram/agent/v1/types/agent_v1conversation_text.py b/src/deepgram/agent/v1/types/agent_v1conversation_text.py index 9888c93b..10148aec 100644 --- a/src/deepgram/agent/v1/types/agent_v1conversation_text.py +++ b/src/deepgram/agent/v1/types/agent_v1conversation_text.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1conversation_text_role import AgentV1ConversationTextRole -class AgentV1ConversationText(UniversalBaseModel): +class AgentV1ConversationText(UncheckedBaseModel): type: typing.Literal["ConversationText"] = pydantic.Field(default="ConversationText") """ Message type identifier for conversation text diff --git a/src/deepgram/agent/v1/types/agent_v1error.py b/src/deepgram/agent/v1/types/agent_v1error.py index e0c01466..aea1228b 100644 --- a/src/deepgram/agent/v1/types/agent_v1error.py +++ b/src/deepgram/agent/v1/types/agent_v1error.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1Error(UniversalBaseModel): +class AgentV1Error(UncheckedBaseModel): type: typing.Literal["Error"] = pydantic.Field(default="Error") """ Message type identifier for error responses diff --git a/src/deepgram/agent/v1/types/agent_v1function_call_request.py b/src/deepgram/agent/v1/types/agent_v1function_call_request.py index 4c5e7c4a..c587938e 100644 --- a/src/deepgram/agent/v1/types/agent_v1function_call_request.py +++ b/src/deepgram/agent/v1/types/agent_v1function_call_request.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1function_call_request_functions_item import AgentV1FunctionCallRequestFunctionsItem -class AgentV1FunctionCallRequest(UniversalBaseModel): +class AgentV1FunctionCallRequest(UncheckedBaseModel): type: typing.Literal["FunctionCallRequest"] = pydantic.Field(default="FunctionCallRequest") """ Message type identifier for function call requests diff --git a/src/deepgram/agent/v1/types/agent_v1function_call_request_functions_item.py b/src/deepgram/agent/v1/types/agent_v1function_call_request_functions_item.py index dcd75dd4..00e70f92 100644 --- a/src/deepgram/agent/v1/types/agent_v1function_call_request_functions_item.py +++ b/src/deepgram/agent/v1/types/agent_v1function_call_request_functions_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1FunctionCallRequestFunctionsItem(UniversalBaseModel): +class AgentV1FunctionCallRequestFunctionsItem(UncheckedBaseModel): id: str = pydantic.Field() """ Unique identifier for the function call diff --git a/src/deepgram/agent/v1/types/agent_v1inject_agent_message.py b/src/deepgram/agent/v1/types/agent_v1inject_agent_message.py index 6711f6dc..a2ca5886 100644 --- a/src/deepgram/agent/v1/types/agent_v1inject_agent_message.py +++ b/src/deepgram/agent/v1/types/agent_v1inject_agent_message.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1InjectAgentMessage(UniversalBaseModel): +class AgentV1InjectAgentMessage(UncheckedBaseModel): type: typing.Literal["InjectAgentMessage"] = pydantic.Field(default="InjectAgentMessage") """ Message type identifier for injecting an agent message diff --git a/src/deepgram/agent/v1/types/agent_v1inject_user_message.py b/src/deepgram/agent/v1/types/agent_v1inject_user_message.py index 78a3ebf9..f10cd987 100644 --- a/src/deepgram/agent/v1/types/agent_v1inject_user_message.py +++ b/src/deepgram/agent/v1/types/agent_v1inject_user_message.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1InjectUserMessage(UniversalBaseModel): +class AgentV1InjectUserMessage(UncheckedBaseModel): type: typing.Literal["InjectUserMessage"] = pydantic.Field(default="InjectUserMessage") """ Message type identifier for injecting a user message diff --git a/src/deepgram/agent/v1/types/agent_v1injection_refused.py b/src/deepgram/agent/v1/types/agent_v1injection_refused.py index b185fccc..619fb932 100644 --- a/src/deepgram/agent/v1/types/agent_v1injection_refused.py +++ b/src/deepgram/agent/v1/types/agent_v1injection_refused.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1InjectionRefused(UniversalBaseModel): +class AgentV1InjectionRefused(UncheckedBaseModel): type: typing.Literal["InjectionRefused"] = pydantic.Field(default="InjectionRefused") """ Message type identifier for injection refused diff --git a/src/deepgram/agent/v1/types/agent_v1keep_alive.py b/src/deepgram/agent/v1/types/agent_v1keep_alive.py index 49266088..4dcfc4e0 100644 --- a/src/deepgram/agent/v1/types/agent_v1keep_alive.py +++ b/src/deepgram/agent/v1/types/agent_v1keep_alive.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1KeepAlive(UniversalBaseModel): +class AgentV1KeepAlive(UncheckedBaseModel): """ Send a control message to the agent """ diff --git a/src/deepgram/agent/v1/types/agent_v1prompt_updated.py b/src/deepgram/agent/v1/types/agent_v1prompt_updated.py index f4827a96..f0840cd5 100644 --- a/src/deepgram/agent/v1/types/agent_v1prompt_updated.py +++ b/src/deepgram/agent/v1/types/agent_v1prompt_updated.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1PromptUpdated(UniversalBaseModel): +class AgentV1PromptUpdated(UncheckedBaseModel): type: typing.Literal["PromptUpdated"] = pydantic.Field(default="PromptUpdated") """ Message type identifier for prompt update confirmation diff --git a/src/deepgram/agent/v1/types/agent_v1receive_function_call_response.py b/src/deepgram/agent/v1/types/agent_v1receive_function_call_response.py index 852aec2b..3501450d 100644 --- a/src/deepgram/agent/v1/types/agent_v1receive_function_call_response.py +++ b/src/deepgram/agent/v1/types/agent_v1receive_function_call_response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1ReceiveFunctionCallResponse(UniversalBaseModel): +class AgentV1ReceiveFunctionCallResponse(UncheckedBaseModel): """ Function call response message used bidirectionally: diff --git a/src/deepgram/agent/v1/types/agent_v1send_function_call_response.py b/src/deepgram/agent/v1/types/agent_v1send_function_call_response.py index 9366862f..6cdef2ff 100644 --- a/src/deepgram/agent/v1/types/agent_v1send_function_call_response.py +++ b/src/deepgram/agent/v1/types/agent_v1send_function_call_response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SendFunctionCallResponse(UniversalBaseModel): +class AgentV1SendFunctionCallResponse(UncheckedBaseModel): """ Function call response message used bidirectionally: diff --git a/src/deepgram/agent/v1/types/agent_v1settings.py b/src/deepgram/agent/v1/types/agent_v1settings.py index 201533d3..11601dfc 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings.py +++ b/src/deepgram/agent/v1/types/agent_v1settings.py @@ -3,13 +3,14 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent import AgentV1SettingsAgent from .agent_v1settings_audio import AgentV1SettingsAudio from .agent_v1settings_flags import AgentV1SettingsFlags -class AgentV1Settings(UniversalBaseModel): +class AgentV1Settings(UncheckedBaseModel): type: typing.Literal["Settings"] = "Settings" tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent.py b/src/deepgram/agent/v1/types/agent_v1settings_agent.py index b51a0247..51686293 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent.py @@ -3,14 +3,15 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent_context import AgentV1SettingsAgentContext from .agent_v1settings_agent_listen import AgentV1SettingsAgentListen from .agent_v1settings_agent_speak import AgentV1SettingsAgentSpeak from .agent_v1settings_agent_think import AgentV1SettingsAgentThink -class AgentV1SettingsAgent(UniversalBaseModel): +class AgentV1SettingsAgent(UncheckedBaseModel): language: typing.Optional[str] = pydantic.Field(default=None) """ Deprecated. Use `listen.provider.language` and `speak.provider.language` fields instead. diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_context.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_context.py index 635f68b5..dabd143a 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_context.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_context.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent_context_messages_item import AgentV1SettingsAgentContextMessagesItem -class AgentV1SettingsAgentContext(UniversalBaseModel): +class AgentV1SettingsAgentContext(UncheckedBaseModel): """ Conversation context including the history of messages and function calls """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_content.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_content.py index 9bc207ab..c1ad74ec 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_content.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_content.py @@ -3,13 +3,14 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent_context_messages_item_content_role import ( AgentV1SettingsAgentContextMessagesItemContentRole, ) -class AgentV1SettingsAgentContextMessagesItemContent(UniversalBaseModel): +class AgentV1SettingsAgentContextMessagesItemContent(UncheckedBaseModel): """ Conversation text as part of the conversation history """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls.py index 6759f8b3..dd693535 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls.py @@ -3,13 +3,14 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent_context_messages_item_function_calls_function_calls_item import ( AgentV1SettingsAgentContextMessagesItemFunctionCallsFunctionCallsItem, ) -class AgentV1SettingsAgentContextMessagesItemFunctionCalls(UniversalBaseModel): +class AgentV1SettingsAgentContextMessagesItemFunctionCalls(UncheckedBaseModel): """ Client-side or server-side function call request and response as part of the conversation history """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls_function_calls_item.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls_function_calls_item.py index 9fead900..7534c9b1 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls_function_calls_item.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_context_messages_item_function_calls_function_calls_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SettingsAgentContextMessagesItemFunctionCallsFunctionCallsItem(UniversalBaseModel): +class AgentV1SettingsAgentContextMessagesItemFunctionCallsFunctionCallsItem(UncheckedBaseModel): id: str = pydantic.Field() """ Unique identifier for the function call diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen.py index 22951f00..9d57e900 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_agent_listen_provider import AgentV1SettingsAgentListenProvider -class AgentV1SettingsAgentListen(UniversalBaseModel): +class AgentV1SettingsAgentListen(UncheckedBaseModel): provider: typing.Optional[AgentV1SettingsAgentListenProvider] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider.py index 273b3157..9800b27d 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider.py @@ -6,10 +6,11 @@ import pydantic import typing_extensions -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel, UnionMetadata -class AgentV1SettingsAgentListenProvider_V1(UniversalBaseModel): +class AgentV1SettingsAgentListenProvider_V1(UncheckedBaseModel): version: typing.Literal["v1"] = "v1" type: typing.Literal["deepgram"] = "deepgram" model: typing.Optional[str] = None @@ -27,7 +28,7 @@ class Config: extra = pydantic.Extra.allow -class AgentV1SettingsAgentListenProvider_V2(UniversalBaseModel): +class AgentV1SettingsAgentListenProvider_V2(UncheckedBaseModel): version: typing.Literal["v2"] = "v2" type: typing.Literal["deepgram"] = "deepgram" model: str @@ -45,5 +46,5 @@ class Config: AgentV1SettingsAgentListenProvider = typing_extensions.Annotated[ typing.Union[AgentV1SettingsAgentListenProvider_V1, AgentV1SettingsAgentListenProvider_V2], - pydantic.Field(discriminator="version"), + UnionMetadata(discriminant="version"), ] diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v1.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v1.py index 1012454d..3370c965 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v1.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v1.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SettingsAgentListenProviderV1(UniversalBaseModel): +class AgentV1SettingsAgentListenProviderV1(UncheckedBaseModel): type: typing.Literal["deepgram"] = pydantic.Field(default="deepgram") """ Provider type for speech-to-text diff --git a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v2.py b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v2.py index cf33274f..5975d23e 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v2.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_agent_listen_provider_v2.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SettingsAgentListenProviderV2(UniversalBaseModel): +class AgentV1SettingsAgentListenProviderV2(UncheckedBaseModel): type: typing.Literal["deepgram"] = pydantic.Field(default="deepgram") """ Provider type for speech-to-text diff --git a/src/deepgram/agent/v1/types/agent_v1settings_applied.py b/src/deepgram/agent/v1/types/agent_v1settings_applied.py index a17ad602..065643b6 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_applied.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_applied.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SettingsApplied(UniversalBaseModel): +class AgentV1SettingsApplied(UncheckedBaseModel): type: typing.Literal["SettingsApplied"] = pydantic.Field(default="SettingsApplied") """ Message type identifier for settings applied confirmation diff --git a/src/deepgram/agent/v1/types/agent_v1settings_audio.py b/src/deepgram/agent/v1/types/agent_v1settings_audio.py index 29350538..8acbec47 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_audio.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_audio.py @@ -3,12 +3,13 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_audio_input import AgentV1SettingsAudioInput from .agent_v1settings_audio_output import AgentV1SettingsAudioOutput -class AgentV1SettingsAudio(UniversalBaseModel): +class AgentV1SettingsAudio(UncheckedBaseModel): input: typing.Optional[AgentV1SettingsAudioInput] = pydantic.Field(default=None) """ Audio input configuration settings. If omitted, defaults to encoding=linear16 and sample_rate=24000. Higher sample rates like 44100 Hz provide better audio quality. diff --git a/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py b/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py index 8b9cae76..59eeb7dd 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_audio_input_encoding import AgentV1SettingsAudioInputEncoding -class AgentV1SettingsAudioInput(UniversalBaseModel): +class AgentV1SettingsAudioInput(UncheckedBaseModel): """ Audio input configuration settings. If omitted, defaults to encoding=linear16 and sample_rate=24000. Higher sample rates like 44100 Hz provide better audio quality. """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py b/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py index e0c0efc8..88c9a109 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .agent_v1settings_audio_output_encoding import AgentV1SettingsAudioOutputEncoding -class AgentV1SettingsAudioOutput(UniversalBaseModel): +class AgentV1SettingsAudioOutput(UncheckedBaseModel): """ Audio output configuration settings """ diff --git a/src/deepgram/agent/v1/types/agent_v1settings_flags.py b/src/deepgram/agent/v1/types/agent_v1settings_flags.py index db3e96cd..91ab8b08 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_flags.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_flags.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SettingsFlags(UniversalBaseModel): +class AgentV1SettingsFlags(UncheckedBaseModel): history: typing.Optional[bool] = pydantic.Field(default=None) """ Enable or disable history message reporting diff --git a/src/deepgram/agent/v1/types/agent_v1speak_updated.py b/src/deepgram/agent/v1/types/agent_v1speak_updated.py index aeba09d8..956dcfd7 100644 --- a/src/deepgram/agent/v1/types/agent_v1speak_updated.py +++ b/src/deepgram/agent/v1/types/agent_v1speak_updated.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1SpeakUpdated(UniversalBaseModel): +class AgentV1SpeakUpdated(UncheckedBaseModel): type: typing.Literal["SpeakUpdated"] = pydantic.Field(default="SpeakUpdated") """ Message type identifier for speak update confirmation diff --git a/src/deepgram/agent/v1/types/agent_v1update_prompt.py b/src/deepgram/agent/v1/types/agent_v1update_prompt.py index a479b01b..8cbada41 100644 --- a/src/deepgram/agent/v1/types/agent_v1update_prompt.py +++ b/src/deepgram/agent/v1/types/agent_v1update_prompt.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1UpdatePrompt(UniversalBaseModel): +class AgentV1UpdatePrompt(UncheckedBaseModel): type: typing.Literal["UpdatePrompt"] = pydantic.Field(default="UpdatePrompt") """ Message type identifier for prompt update request diff --git a/src/deepgram/agent/v1/types/agent_v1update_speak.py b/src/deepgram/agent/v1/types/agent_v1update_speak.py index 7bf9e7d0..4afc8d37 100644 --- a/src/deepgram/agent/v1/types/agent_v1update_speak.py +++ b/src/deepgram/agent/v1/types/agent_v1update_speak.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from ....types.speak_settings_v1 import SpeakSettingsV1 -class AgentV1UpdateSpeak(UniversalBaseModel): +class AgentV1UpdateSpeak(UncheckedBaseModel): type: typing.Literal["UpdateSpeak"] = pydantic.Field(default="UpdateSpeak") """ Message type identifier for updating the speak model diff --git a/src/deepgram/agent/v1/types/agent_v1user_started_speaking.py b/src/deepgram/agent/v1/types/agent_v1user_started_speaking.py index ac4d838a..afc96fed 100644 --- a/src/deepgram/agent/v1/types/agent_v1user_started_speaking.py +++ b/src/deepgram/agent/v1/types/agent_v1user_started_speaking.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1UserStartedSpeaking(UniversalBaseModel): +class AgentV1UserStartedSpeaking(UncheckedBaseModel): type: typing.Literal["UserStartedSpeaking"] = pydantic.Field(default="UserStartedSpeaking") """ Message type identifier indicating that the user has begun speaking diff --git a/src/deepgram/agent/v1/types/agent_v1warning.py b/src/deepgram/agent/v1/types/agent_v1warning.py index cdfacea7..c4741050 100644 --- a/src/deepgram/agent/v1/types/agent_v1warning.py +++ b/src/deepgram/agent/v1/types/agent_v1warning.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1Warning(UniversalBaseModel): +class AgentV1Warning(UncheckedBaseModel): """ Notifies the client of non-fatal errors or warnings """ diff --git a/src/deepgram/agent/v1/types/agent_v1welcome.py b/src/deepgram/agent/v1/types/agent_v1welcome.py index 972f8104..128700c0 100644 --- a/src/deepgram/agent/v1/types/agent_v1welcome.py +++ b/src/deepgram/agent/v1/types/agent_v1welcome.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class AgentV1Welcome(UniversalBaseModel): +class AgentV1Welcome(UncheckedBaseModel): type: typing.Literal["Welcome"] = pydantic.Field(default="Welcome") """ Message type identifier for welcome message diff --git a/src/deepgram/auth/v1/tokens/raw_client.py b/src/deepgram/auth/v1/tokens/raw_client.py index b8d45f79..c2a652a4 100644 --- a/src/deepgram/auth/v1/tokens/raw_client.py +++ b/src/deepgram/auth/v1/tokens/raw_client.py @@ -6,8 +6,8 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from ....types.grant_v1response import GrantV1Response @@ -55,7 +55,7 @@ def grant( if 200 <= _response.status_code < 300: _data = typing.cast( GrantV1Response, - parse_obj_as( + construct_type( type_=GrantV1Response, # type: ignore object_=_response.json(), ), @@ -66,7 +66,7 @@ def grant( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -118,7 +118,7 @@ async def grant( if 200 <= _response.status_code < 300: _data = typing.cast( GrantV1Response, - parse_obj_as( + construct_type( type_=GrantV1Response, # type: ignore object_=_response.json(), ), @@ -129,7 +129,7 @@ async def grant( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/core/__init__.py b/src/deepgram/core/__init__.py index 421d242d..8547a17c 100644 --- a/src/deepgram/core/__init__.py +++ b/src/deepgram/core/__init__.py @@ -27,6 +27,7 @@ from .remove_none_from_dict import remove_none_from_dict from .request_options import RequestOptions from .serialization import FieldMetadata, convert_and_respect_annotation_metadata + from .unchecked_base_model import UncheckedBaseModel, UnionMetadata, construct_type from .websocket_compat import InvalidWebSocketStatus, get_status_code _dynamic_imports: typing.Dict[str, str] = { "ApiError": ".api_error", @@ -44,8 +45,11 @@ "InvalidWebSocketStatus": ".websocket_compat", "RequestOptions": ".request_options", "SyncClientWrapper": ".client_wrapper", + "UncheckedBaseModel": ".unchecked_base_model", + "UnionMetadata": ".unchecked_base_model", "UniversalBaseModel": ".pydantic_utilities", "UniversalRootModel": ".pydantic_utilities", + "construct_type": ".unchecked_base_model", "convert_and_respect_annotation_metadata": ".serialization", "convert_file_dict_to_httpx_tuples": ".file", "encode_query": ".query_encoder", @@ -98,8 +102,11 @@ def __dir__(): "InvalidWebSocketStatus", "RequestOptions", "SyncClientWrapper", + "UncheckedBaseModel", + "UnionMetadata", "UniversalBaseModel", "UniversalRootModel", + "construct_type", "convert_and_respect_annotation_metadata", "convert_file_dict_to_httpx_tuples", "encode_query", diff --git a/src/deepgram/core/client_wrapper.py b/src/deepgram/core/client_wrapper.py index 36d0f291..e6d5f3a7 100644 --- a/src/deepgram/core/client_wrapper.py +++ b/src/deepgram/core/client_wrapper.py @@ -25,12 +25,11 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "deepgram-sdk/6.0.0-rc.2", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "deepgram-sdk", - "X-Fern-SDK-Version": "6.0.0-rc.2", + "X-Fern-SDK-Version": "0.0.333", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Token {self.api_key}" diff --git a/src/deepgram/core/unchecked_base_model.py b/src/deepgram/core/unchecked_base_model.py new file mode 100644 index 00000000..9ea71ca6 --- /dev/null +++ b/src/deepgram/core/unchecked_base_model.py @@ -0,0 +1,376 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import inspect +import typing +import uuid + +import pydantic +import typing_extensions +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + ModelField, + UniversalBaseModel, + get_args, + get_origin, + is_literal_type, + is_union, + parse_date, + parse_datetime, + parse_obj_as, +) +from .serialization import get_field_to_alias_mapping +from pydantic_core import PydanticUndefined + + +class UnionMetadata: + discriminant: str + + def __init__(self, *, discriminant: str) -> None: + self.discriminant = discriminant + + +Model = typing.TypeVar("Model", bound=pydantic.BaseModel) + + +class UncheckedBaseModel(UniversalBaseModel): + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow") # type: ignore # Pydantic v2 + else: + + class Config: + extra = pydantic.Extra.allow + + @classmethod + def model_construct( + cls: typing.Type["Model"], + _fields_set: typing.Optional[typing.Set[str]] = None, + **values: typing.Any, + ) -> "Model": + # Fallback construct function to the specified override below. + return cls.construct(_fields_set=_fields_set, **values) + + # Allow construct to not validate model + # Implementation taken from: https://github.com/pydantic/pydantic/issues/1168#issuecomment-817742836 + @classmethod + def construct( + cls: typing.Type["Model"], + _fields_set: typing.Optional[typing.Set[str]] = None, + **values: typing.Any, + ) -> "Model": + m = cls.__new__(cls) + fields_values = {} + + if _fields_set is None: + _fields_set = set(values.keys()) + + fields = _get_model_fields(cls) + populate_by_name = _get_is_populate_by_name(cls) + field_aliases = get_field_to_alias_mapping(cls) + + for name, field in fields.items(): + # Key here is only used to pull data from the values dict + # you should always use the NAME of the field to for field_values, etc. + # because that's how the object is constructed from a pydantic perspective + key = field.alias + if (key is None or field.alias == name) and name in field_aliases: + key = field_aliases[name] + + if key is None or (key not in values and populate_by_name): # Added this to allow population by field name + key = name + + if key in values: + if IS_PYDANTIC_V2: + type_ = field.annotation # type: ignore # Pydantic v2 + else: + type_ = typing.cast(typing.Type, field.outer_type_) # type: ignore # Pydantic < v1.10.15 + + fields_values[name] = ( + construct_type(object_=values[key], type_=type_) if type_ is not None else values[key] + ) + _fields_set.add(name) + else: + default = _get_field_default(field) + fields_values[name] = default + + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default != None and default != PydanticUndefined: + _fields_set.add(name) + + # Add extras back in + extras = {} + pydantic_alias_fields = [field.alias for field in fields.values()] + internal_alias_fields = list(field_aliases.values()) + for key, value in values.items(): + # If the key is not a field by name, nor an alias to a field, then it's extra + if (key not in pydantic_alias_fields and key not in internal_alias_fields) and key not in fields: + if IS_PYDANTIC_V2: + extras[key] = value + else: + _fields_set.add(key) + fields_values[key] = value + + object.__setattr__(m, "__dict__", fields_values) + + if IS_PYDANTIC_V2: + object.__setattr__(m, "__pydantic_private__", None) + object.__setattr__(m, "__pydantic_extra__", extras) + object.__setattr__(m, "__pydantic_fields_set__", _fields_set) + else: + object.__setattr__(m, "__fields_set__", _fields_set) + m._init_private_attributes() # type: ignore # Pydantic v1 + return m + + +def _validate_collection_items_compatible(collection: typing.Any, target_type: typing.Type[typing.Any]) -> bool: + """ + Validate that all items in a collection are compatible with the target type. + + Args: + collection: The collection to validate (list, set, or dict values) + target_type: The target type to validate against + + Returns: + True if all items are compatible, False otherwise + """ + if inspect.isclass(target_type) and issubclass(target_type, pydantic.BaseModel): + for item in collection: + try: + # Try to validate the item against the target type + if isinstance(item, dict): + parse_obj_as(target_type, item) + else: + # If it's not a dict, it might already be the right type + if not isinstance(item, target_type): + return False + except Exception: + return False + return True + + +def _convert_undiscriminated_union_type(union_type: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: + inner_types = get_args(union_type) + if typing.Any in inner_types: + return object_ + + for inner_type in inner_types: + # Handle lists of objects that need parsing + if get_origin(inner_type) is list and isinstance(object_, list): + list_inner_type = get_args(inner_type)[0] + try: + if inspect.isclass(list_inner_type) and issubclass(list_inner_type, pydantic.BaseModel): + # Validate that all items in the list are compatible with the target type + if _validate_collection_items_compatible(object_, list_inner_type): + parsed_list = [parse_obj_as(object_=item, type_=list_inner_type) for item in object_] + return parsed_list + except Exception: + pass + + try: + if inspect.isclass(inner_type) and issubclass(inner_type, pydantic.BaseModel): + # Attempt a validated parse until one works + return parse_obj_as(inner_type, object_) + except Exception: + continue + + # If none of the types work, try matching literal fields first, then fall back + # First pass: try types where all literal fields match the object's values + for inner_type in inner_types: + if inspect.isclass(inner_type) and issubclass(inner_type, pydantic.BaseModel): + fields = _get_model_fields(inner_type) + literal_fields_match = True + + for field_name, field in fields.items(): + # Check if this field has a Literal type + if IS_PYDANTIC_V2: + field_type = field.annotation # type: ignore # Pydantic v2 + else: + field_type = field.outer_type_ # type: ignore # Pydantic v1 + + if is_literal_type(field_type): # type: ignore[arg-type] + field_default = _get_field_default(field) + name_or_alias = get_field_to_alias_mapping(inner_type).get(field_name, field_name) + # Get the value from the object + if isinstance(object_, dict): + object_value = object_.get(name_or_alias) + else: + object_value = getattr(object_, name_or_alias, None) + + # If the literal field value doesn't match, this type is not a match + if object_value is not None and field_default != object_value: + literal_fields_match = False + break + + # If all literal fields match, try to construct this type + if literal_fields_match: + try: + return construct_type(object_=object_, type_=inner_type) + except Exception: + continue + + # Second pass: if no literal matches, just return the first successful cast + for inner_type in inner_types: + try: + return construct_type(object_=object_, type_=inner_type) + except Exception: + continue + + +def _convert_union_type(type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: + base_type = get_origin(type_) or type_ + union_type = type_ + if base_type == typing_extensions.Annotated: # type: ignore[comparison-overlap] + union_type = get_args(type_)[0] + annotated_metadata = get_args(type_)[1:] + for metadata in annotated_metadata: + if isinstance(metadata, UnionMetadata): + try: + # Cast to the correct type, based on the discriminant + for inner_type in get_args(union_type): + try: + objects_discriminant = getattr(object_, metadata.discriminant) + except: + objects_discriminant = object_[metadata.discriminant] + if inner_type.__fields__[metadata.discriminant].default == objects_discriminant: + return construct_type(object_=object_, type_=inner_type) + except Exception: + # Allow to fall through to our regular union handling + pass + return _convert_undiscriminated_union_type(union_type, object_) + + +def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: + """ + Here we are essentially creating the same `construct` method in spirit as the above, but for all types, not just + Pydantic models. + The idea is to essentially attempt to coerce object_ to type_ (recursively) + """ + # Short circuit when dealing with optionals, don't try to coerces None to a type + if object_ is None: + return None + + base_type = get_origin(type_) or type_ + is_annotated = base_type == typing_extensions.Annotated # type: ignore[comparison-overlap] + maybe_annotation_members = get_args(type_) + is_annotated_union = is_annotated and is_union(get_origin(maybe_annotation_members[0])) + + if base_type == typing.Any: # type: ignore[comparison-overlap] + return object_ + + if base_type == dict: + if not isinstance(object_, typing.Mapping): + return object_ + + key_type, items_type = get_args(type_) + d = { + construct_type(object_=key, type_=key_type): construct_type(object_=item, type_=items_type) + for key, item in object_.items() + } + return d + + if base_type == list: + if not isinstance(object_, list): + return object_ + + inner_type = get_args(type_)[0] + return [construct_type(object_=entry, type_=inner_type) for entry in object_] + + if base_type == set: + if not isinstance(object_, set) and not isinstance(object_, list): + return object_ + + inner_type = get_args(type_)[0] + return {construct_type(object_=entry, type_=inner_type) for entry in object_} + + if is_union(base_type) or is_annotated_union: + return _convert_union_type(type_, object_) + + # Cannot do an `issubclass` with a literal type, let's also just confirm we have a class before this call + if ( + object_ is not None + and not is_literal_type(type_) + and ( + (inspect.isclass(base_type) and issubclass(base_type, pydantic.BaseModel)) + or ( + is_annotated + and inspect.isclass(maybe_annotation_members[0]) + and issubclass(maybe_annotation_members[0], pydantic.BaseModel) + ) + ) + ): + if IS_PYDANTIC_V2: + return type_.model_construct(**object_) + else: + return type_.construct(**object_) + + if base_type == dt.datetime: + try: + return parse_datetime(object_) + except Exception: + return object_ + + if base_type == dt.date: + try: + return parse_date(object_) + except Exception: + return object_ + + if base_type == uuid.UUID: + try: + return uuid.UUID(object_) + except Exception: + return object_ + + if base_type == int: + try: + return int(object_) + except Exception: + return object_ + + if base_type == bool: + try: + if isinstance(object_, str): + stringified_object = object_.lower() + return stringified_object == "true" or stringified_object == "1" + + return bool(object_) + except Exception: + return object_ + + return object_ + + +def _get_is_populate_by_name(model: typing.Type["Model"]) -> bool: + if IS_PYDANTIC_V2: + return model.model_config.get("populate_by_name", False) # type: ignore # Pydantic v2 + return model.__config__.allow_population_by_field_name # type: ignore # Pydantic v1 + + +PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo] + + +# Pydantic V1 swapped the typing of __fields__'s values from ModelField to FieldInfo +# And so we try to handle both V1 cases, as well as V2 (FieldInfo from model.model_fields) +def _get_model_fields( + model: typing.Type["Model"], +) -> typing.Mapping[str, PydanticField]: + if IS_PYDANTIC_V2: + return model.model_fields # type: ignore # Pydantic v2 + else: + return model.__fields__ # type: ignore # Pydantic v1 + + +def _get_field_default(field: PydanticField) -> typing.Any: + try: + value = field.get_default() # type: ignore # Pydantic < v1.10.15 + except: + value = field.default + if IS_PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value diff --git a/src/deepgram/listen/v1/client.py b/src/deepgram/listen/v1/client.py index 9abf8aba..6526f830 100644 --- a/src/deepgram/listen/v1/client.py +++ b/src/deepgram/listen/v1/client.py @@ -55,10 +55,10 @@ def connect( dictation: typing.Optional[str] = None, encoding: typing.Optional[str] = None, endpointing: typing.Optional[str] = None, - extra: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + extra: typing.Optional[str] = None, interim_results: typing.Optional[str] = None, - keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - keywords: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keyterm: typing.Optional[str] = None, + keywords: typing.Optional[str] = None, language: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, model: str, @@ -66,12 +66,12 @@ def connect( numerals: typing.Optional[str] = None, profanity_filter: typing.Optional[str] = None, punctuate: typing.Optional[str] = None, - redact: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - replace: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + redact: typing.Optional[str] = None, + replace: typing.Optional[str] = None, sample_rate: typing.Optional[str] = None, - search: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + search: typing.Optional[str] = None, smart_format: typing.Optional[str] = None, - tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + tag: typing.Optional[str] = None, utterance_end_ms: typing.Optional[str] = None, vad_events: typing.Optional[str] = None, version: typing.Optional[str] = None, @@ -256,10 +256,10 @@ async def connect( dictation: typing.Optional[str] = None, encoding: typing.Optional[str] = None, endpointing: typing.Optional[str] = None, - extra: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + extra: typing.Optional[str] = None, interim_results: typing.Optional[str] = None, - keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - keywords: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keyterm: typing.Optional[str] = None, + keywords: typing.Optional[str] = None, language: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, model: str, @@ -267,12 +267,12 @@ async def connect( numerals: typing.Optional[str] = None, profanity_filter: typing.Optional[str] = None, punctuate: typing.Optional[str] = None, - redact: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - replace: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + redact: typing.Optional[str] = None, + replace: typing.Optional[str] = None, sample_rate: typing.Optional[str] = None, - search: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + search: typing.Optional[str] = None, smart_format: typing.Optional[str] = None, - tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + tag: typing.Optional[str] = None, utterance_end_ms: typing.Optional[str] = None, vad_events: typing.Optional[str] = None, version: typing.Optional[str] = None, diff --git a/src/deepgram/listen/v1/media/raw_client.py b/src/deepgram/listen/v1/media/raw_client.py index d1c7d675..830d4259 100644 --- a/src/deepgram/listen/v1/media/raw_client.py +++ b/src/deepgram/listen/v1/media/raw_client.py @@ -6,8 +6,8 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from .types.media_transcribe_request_callback_method import MediaTranscribeRequestCallbackMethod from .types.media_transcribe_request_custom_intent_mode import MediaTranscribeRequestCustomIntentMode @@ -246,7 +246,7 @@ def transcribe_url( if 200 <= _response.status_code < 300: _data = typing.cast( MediaTranscribeResponse, - parse_obj_as( + construct_type( type_=MediaTranscribeResponse, # type: ignore object_=_response.json(), ), @@ -257,7 +257,7 @@ def transcribe_url( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -486,7 +486,7 @@ def transcribe_file( if 200 <= _response.status_code < 300: _data = typing.cast( MediaTranscribeResponse, - parse_obj_as( + construct_type( type_=MediaTranscribeResponse, # type: ignore object_=_response.json(), ), @@ -497,7 +497,7 @@ def transcribe_file( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -733,7 +733,7 @@ async def transcribe_url( if 200 <= _response.status_code < 300: _data = typing.cast( MediaTranscribeResponse, - parse_obj_as( + construct_type( type_=MediaTranscribeResponse, # type: ignore object_=_response.json(), ), @@ -744,7 +744,7 @@ async def transcribe_url( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -973,7 +973,7 @@ async def transcribe_file( if 200 <= _response.status_code < 300: _data = typing.cast( MediaTranscribeResponse, - parse_obj_as( + construct_type( type_=MediaTranscribeResponse, # type: ignore object_=_response.json(), ), @@ -984,7 +984,7 @@ async def transcribe_file( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/listen/v1/types/listen_v1close_stream.py b/src/deepgram/listen/v1/types/listen_v1close_stream.py index 6c11646f..459f290d 100644 --- a/src/deepgram/listen/v1/types/listen_v1close_stream.py +++ b/src/deepgram/listen/v1/types/listen_v1close_stream.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1close_stream_type import ListenV1CloseStreamType -class ListenV1CloseStream(UniversalBaseModel): +class ListenV1CloseStream(UncheckedBaseModel): type: ListenV1CloseStreamType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1finalize.py b/src/deepgram/listen/v1/types/listen_v1finalize.py index ffd48baa..5c11a0ad 100644 --- a/src/deepgram/listen/v1/types/listen_v1finalize.py +++ b/src/deepgram/listen/v1/types/listen_v1finalize.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1finalize_type import ListenV1FinalizeType -class ListenV1Finalize(UniversalBaseModel): +class ListenV1Finalize(UncheckedBaseModel): type: ListenV1FinalizeType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1keep_alive.py b/src/deepgram/listen/v1/types/listen_v1keep_alive.py index 96d3e67a..beeb1375 100644 --- a/src/deepgram/listen/v1/types/listen_v1keep_alive.py +++ b/src/deepgram/listen/v1/types/listen_v1keep_alive.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1keep_alive_type import ListenV1KeepAliveType -class ListenV1KeepAlive(UniversalBaseModel): +class ListenV1KeepAlive(UncheckedBaseModel): type: ListenV1KeepAliveType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1metadata.py b/src/deepgram/listen/v1/types/listen_v1metadata.py index d86a5253..5a048330 100644 --- a/src/deepgram/listen/v1/types/listen_v1metadata.py +++ b/src/deepgram/listen/v1/types/listen_v1metadata.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1Metadata(UniversalBaseModel): +class ListenV1Metadata(UncheckedBaseModel): type: typing.Literal["Metadata"] = pydantic.Field(default="Metadata") """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1results.py b/src/deepgram/listen/v1/types/listen_v1results.py index 9479f87d..2ac0f05c 100644 --- a/src/deepgram/listen/v1/types/listen_v1results.py +++ b/src/deepgram/listen/v1/types/listen_v1results.py @@ -3,13 +3,14 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1results_channel import ListenV1ResultsChannel from .listen_v1results_entities_item import ListenV1ResultsEntitiesItem from .listen_v1results_metadata import ListenV1ResultsMetadata -class ListenV1Results(UniversalBaseModel): +class ListenV1Results(UncheckedBaseModel): type: typing.Literal["Results"] = pydantic.Field(default="Results") """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1results_channel.py b/src/deepgram/listen/v1/types/listen_v1results_channel.py index ce58c5f3..139d6816 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_channel.py +++ b/src/deepgram/listen/v1/types/listen_v1results_channel.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1results_channel_alternatives_item import ListenV1ResultsChannelAlternativesItem -class ListenV1ResultsChannel(UniversalBaseModel): +class ListenV1ResultsChannel(UncheckedBaseModel): alternatives: typing.List[ListenV1ResultsChannelAlternativesItem] if IS_PYDANTIC_V2: diff --git a/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item.py b/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item.py index c8e0703c..c9721805 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item.py +++ b/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1results_channel_alternatives_item_words_item import ListenV1ResultsChannelAlternativesItemWordsItem -class ListenV1ResultsChannelAlternativesItem(UniversalBaseModel): +class ListenV1ResultsChannelAlternativesItem(UncheckedBaseModel): transcript: str = pydantic.Field() """ The transcript of the transcription diff --git a/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item_words_item.py b/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item_words_item.py index 2cc3686f..30060dda 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item_words_item.py +++ b/src/deepgram/listen/v1/types/listen_v1results_channel_alternatives_item_words_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResultsChannelAlternativesItemWordsItem(UniversalBaseModel): +class ListenV1ResultsChannelAlternativesItemWordsItem(UncheckedBaseModel): word: str = pydantic.Field() """ The word of the transcription diff --git a/src/deepgram/listen/v1/types/listen_v1results_entities_item.py b/src/deepgram/listen/v1/types/listen_v1results_entities_item.py index f8d5fb3a..567285ae 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_entities_item.py +++ b/src/deepgram/listen/v1/types/listen_v1results_entities_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResultsEntitiesItem(UniversalBaseModel): +class ListenV1ResultsEntitiesItem(UncheckedBaseModel): label: str = pydantic.Field() """ The type/category of the entity (e.g., NAME, PHONE_NUMBER, EMAIL_ADDRESS, ORGANIZATION, CARDINAL) diff --git a/src/deepgram/listen/v1/types/listen_v1results_metadata.py b/src/deepgram/listen/v1/types/listen_v1results_metadata.py index 92518626..8e086c1c 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_metadata.py +++ b/src/deepgram/listen/v1/types/listen_v1results_metadata.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v1results_metadata_model_info import ListenV1ResultsMetadataModelInfo -class ListenV1ResultsMetadata(UniversalBaseModel): +class ListenV1ResultsMetadata(UncheckedBaseModel): request_id: str = pydantic.Field() """ The request ID diff --git a/src/deepgram/listen/v1/types/listen_v1results_metadata_model_info.py b/src/deepgram/listen/v1/types/listen_v1results_metadata_model_info.py index 19e04fa8..a1a971b7 100644 --- a/src/deepgram/listen/v1/types/listen_v1results_metadata_model_info.py +++ b/src/deepgram/listen/v1/types/listen_v1results_metadata_model_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResultsMetadataModelInfo(UniversalBaseModel): +class ListenV1ResultsMetadataModelInfo(UncheckedBaseModel): name: str = pydantic.Field() """ The name of the model diff --git a/src/deepgram/listen/v1/types/listen_v1speech_started.py b/src/deepgram/listen/v1/types/listen_v1speech_started.py index ce42f749..ff986c28 100644 --- a/src/deepgram/listen/v1/types/listen_v1speech_started.py +++ b/src/deepgram/listen/v1/types/listen_v1speech_started.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1SpeechStarted(UniversalBaseModel): +class ListenV1SpeechStarted(UncheckedBaseModel): type: typing.Literal["SpeechStarted"] = pydantic.Field(default="SpeechStarted") """ Message type identifier diff --git a/src/deepgram/listen/v1/types/listen_v1utterance_end.py b/src/deepgram/listen/v1/types/listen_v1utterance_end.py index 39cb1100..893468fc 100644 --- a/src/deepgram/listen/v1/types/listen_v1utterance_end.py +++ b/src/deepgram/listen/v1/types/listen_v1utterance_end.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV1UtteranceEnd(UniversalBaseModel): +class ListenV1UtteranceEnd(UncheckedBaseModel): type: typing.Literal["UtteranceEnd"] = pydantic.Field(default="UtteranceEnd") """ Message type identifier diff --git a/src/deepgram/listen/v2/client.py b/src/deepgram/listen/v2/client.py index 949f0c75..9e85c73d 100644 --- a/src/deepgram/listen/v2/client.py +++ b/src/deepgram/listen/v2/client.py @@ -46,9 +46,9 @@ def connect( eager_eot_threshold: typing.Optional[str] = None, eot_threshold: typing.Optional[str] = None, eot_timeout_ms: typing.Optional[str] = None, - keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keyterm: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, - tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + tag: typing.Optional[str] = None, authorization: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[V2SocketClient]: @@ -70,13 +70,11 @@ def connect( eot_timeout_ms : typing.Optional[str] - keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Keyterm prompting can improve recognition of specialized terminology. Pass a single string or a list of strings. + keyterm : typing.Optional[str] mip_opt_out : typing.Optional[str] - tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Label your requests for the purpose of identification during usage reporting. Pass a single string or a list of strings. + tag : typing.Optional[str] authorization : typing.Optional[str] Use your API key for authentication, or alternatively generate a [temporary token](/guides/fundamentals/token-based-authentication) and pass it via the `token` query parameter. @@ -163,9 +161,9 @@ async def connect( eager_eot_threshold: typing.Optional[str] = None, eot_threshold: typing.Optional[str] = None, eot_timeout_ms: typing.Optional[str] = None, - keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keyterm: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, - tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + tag: typing.Optional[str] = None, authorization: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[AsyncV2SocketClient]: @@ -187,13 +185,11 @@ async def connect( eot_timeout_ms : typing.Optional[str] - keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Keyterm prompting can improve recognition of specialized terminology. Pass a single string or a list of strings. + keyterm : typing.Optional[str] mip_opt_out : typing.Optional[str] - tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Label your requests for the purpose of identification during usage reporting. Pass a single string or a list of strings. + tag : typing.Optional[str] authorization : typing.Optional[str] Use your API key for authentication, or alternatively generate a [temporary token](/guides/fundamentals/token-based-authentication) and pass it via the `token` query parameter. diff --git a/src/deepgram/listen/v2/types/listen_v2close_stream.py b/src/deepgram/listen/v2/types/listen_v2close_stream.py index 00376ced..1c95ec7a 100644 --- a/src/deepgram/listen/v2/types/listen_v2close_stream.py +++ b/src/deepgram/listen/v2/types/listen_v2close_stream.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v2close_stream_type import ListenV2CloseStreamType -class ListenV2CloseStream(UniversalBaseModel): +class ListenV2CloseStream(UncheckedBaseModel): type: ListenV2CloseStreamType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/listen/v2/types/listen_v2connected.py b/src/deepgram/listen/v2/types/listen_v2connected.py index 29108f24..b174be68 100644 --- a/src/deepgram/listen/v2/types/listen_v2connected.py +++ b/src/deepgram/listen/v2/types/listen_v2connected.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV2Connected(UniversalBaseModel): +class ListenV2Connected(UncheckedBaseModel): type: typing.Literal["Connected"] = pydantic.Field(default="Connected") """ Message type identifier diff --git a/src/deepgram/listen/v2/types/listen_v2fatal_error.py b/src/deepgram/listen/v2/types/listen_v2fatal_error.py index 1eccfabc..0e65c00e 100644 --- a/src/deepgram/listen/v2/types/listen_v2fatal_error.py +++ b/src/deepgram/listen/v2/types/listen_v2fatal_error.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV2FatalError(UniversalBaseModel): +class ListenV2FatalError(UncheckedBaseModel): type: typing.Literal["Error"] = pydantic.Field(default="Error") """ Message type identifier diff --git a/src/deepgram/listen/v2/types/listen_v2turn_info.py b/src/deepgram/listen/v2/types/listen_v2turn_info.py index 80006b6b..7ba2770c 100644 --- a/src/deepgram/listen/v2/types/listen_v2turn_info.py +++ b/src/deepgram/listen/v2/types/listen_v2turn_info.py @@ -3,12 +3,13 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .listen_v2turn_info_event import ListenV2TurnInfoEvent from .listen_v2turn_info_words_item import ListenV2TurnInfoWordsItem -class ListenV2TurnInfo(UniversalBaseModel): +class ListenV2TurnInfo(UncheckedBaseModel): """ Describes the current turn and latest state of the turn """ diff --git a/src/deepgram/listen/v2/types/listen_v2turn_info_words_item.py b/src/deepgram/listen/v2/types/listen_v2turn_info_words_item.py index 58ae2f98..b61097a0 100644 --- a/src/deepgram/listen/v2/types/listen_v2turn_info_words_item.py +++ b/src/deepgram/listen/v2/types/listen_v2turn_info_words_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class ListenV2TurnInfoWordsItem(UniversalBaseModel): +class ListenV2TurnInfoWordsItem(UncheckedBaseModel): word: str = pydantic.Field() """ The individual punctuated, properly-cased word from the transcript diff --git a/src/deepgram/manage/v1/models/raw_client.py b/src/deepgram/manage/v1/models/raw_client.py index f1300e7f..645700c9 100644 --- a/src/deepgram/manage/v1/models/raw_client.py +++ b/src/deepgram/manage/v1/models/raw_client.py @@ -7,8 +7,8 @@ from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse from ....core.jsonable_encoder import jsonable_encoder -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from ....types.get_model_v1response import GetModelV1Response from ....types.list_models_v1response import ListModelsV1Response @@ -50,7 +50,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListModelsV1Response, - parse_obj_as( + construct_type( type_=ListModelsV1Response, # type: ignore object_=_response.json(), ), @@ -61,7 +61,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -101,7 +101,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetModelV1Response, - parse_obj_as( + construct_type( type_=GetModelV1Response, # type: ignore object_=_response.json(), ), @@ -112,7 +112,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -160,7 +160,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListModelsV1Response, - parse_obj_as( + construct_type( type_=ListModelsV1Response, # type: ignore object_=_response.json(), ), @@ -171,7 +171,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -211,7 +211,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetModelV1Response, - parse_obj_as( + construct_type( type_=GetModelV1Response, # type: ignore object_=_response.json(), ), @@ -222,7 +222,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/billing/balances/raw_client.py b/src/deepgram/manage/v1/projects/billing/balances/raw_client.py index 744135f4..c3794fb5 100644 --- a/src/deepgram/manage/v1/projects/billing/balances/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/balances/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.get_project_balance_v1response import GetProjectBalanceV1Response from ......types.list_project_balances_v1response import ListProjectBalancesV1Response @@ -47,7 +47,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectBalancesV1Response, - parse_obj_as( + construct_type( type_=ListProjectBalancesV1Response, # type: ignore object_=_response.json(), ), @@ -58,7 +58,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -101,7 +101,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectBalanceV1Response, - parse_obj_as( + construct_type( type_=GetProjectBalanceV1Response, # type: ignore object_=_response.json(), ), @@ -112,7 +112,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -157,7 +157,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectBalancesV1Response, - parse_obj_as( + construct_type( type_=ListProjectBalancesV1Response, # type: ignore object_=_response.json(), ), @@ -168,7 +168,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -211,7 +211,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectBalanceV1Response, - parse_obj_as( + construct_type( type_=GetProjectBalanceV1Response, # type: ignore object_=_response.json(), ), @@ -222,7 +222,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py b/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py index c34e4eb9..42bcf865 100644 --- a/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.billing_breakdown_v1response import BillingBreakdownV1Response from .types.breakdown_list_request_deployment import BreakdownListRequestDeployment @@ -90,7 +90,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( BillingBreakdownV1Response, - parse_obj_as( + construct_type( type_=BillingBreakdownV1Response, # type: ignore object_=_response.json(), ), @@ -101,7 +101,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -188,7 +188,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( BillingBreakdownV1Response, - parse_obj_as( + construct_type( type_=BillingBreakdownV1Response, # type: ignore object_=_response.json(), ), @@ -199,7 +199,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/billing/fields/raw_client.py b/src/deepgram/manage/v1/projects/billing/fields/raw_client.py index 548efb07..ec97bccc 100644 --- a/src/deepgram/manage/v1/projects/billing/fields/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/fields/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.list_billing_fields_v1response import ListBillingFieldsV1Response @@ -61,7 +61,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListBillingFieldsV1Response, - parse_obj_as( + construct_type( type_=ListBillingFieldsV1Response, # type: ignore object_=_response.json(), ), @@ -72,7 +72,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -132,7 +132,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListBillingFieldsV1Response, - parse_obj_as( + construct_type( type_=ListBillingFieldsV1Response, # type: ignore object_=_response.json(), ), @@ -143,7 +143,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py b/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py index 7839ad56..02621660 100644 --- a/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.list_project_purchases_v1response import ListProjectPurchasesV1Response @@ -56,7 +56,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectPurchasesV1Response, - parse_obj_as( + construct_type( type_=ListProjectPurchasesV1Response, # type: ignore object_=_response.json(), ), @@ -67,7 +67,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -122,7 +122,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectPurchasesV1Response, - parse_obj_as( + construct_type( type_=ListProjectPurchasesV1Response, # type: ignore object_=_response.json(), ), @@ -133,7 +133,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/keys/raw_client.py b/src/deepgram/manage/v1/projects/keys/raw_client.py index 435f70eb..60c81ff6 100644 --- a/src/deepgram/manage/v1/projects/keys/raw_client.py +++ b/src/deepgram/manage/v1/projects/keys/raw_client.py @@ -7,8 +7,8 @@ from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as from .....core.request_options import RequestOptions +from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError from .....types.create_key_v1request_one import CreateKeyV1RequestOne from .....types.create_key_v1response import CreateKeyV1Response @@ -64,7 +64,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectKeysV1Response, - parse_obj_as( + construct_type( type_=ListProjectKeysV1Response, # type: ignore object_=_response.json(), ), @@ -75,7 +75,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -126,7 +126,7 @@ def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateKeyV1Response, - parse_obj_as( + construct_type( type_=CreateKeyV1Response, # type: ignore object_=_response.json(), ), @@ -137,7 +137,7 @@ def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -180,7 +180,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectKeyV1Response, - parse_obj_as( + construct_type( type_=GetProjectKeyV1Response, # type: ignore object_=_response.json(), ), @@ -191,7 +191,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -234,7 +234,7 @@ def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectKeyV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectKeyV1Response, # type: ignore object_=_response.json(), ), @@ -245,7 +245,7 @@ def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -300,7 +300,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectKeysV1Response, - parse_obj_as( + construct_type( type_=ListProjectKeysV1Response, # type: ignore object_=_response.json(), ), @@ -311,7 +311,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -362,7 +362,7 @@ async def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateKeyV1Response, - parse_obj_as( + construct_type( type_=CreateKeyV1Response, # type: ignore object_=_response.json(), ), @@ -373,7 +373,7 @@ async def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -416,7 +416,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectKeyV1Response, - parse_obj_as( + construct_type( type_=GetProjectKeyV1Response, # type: ignore object_=_response.json(), ), @@ -427,7 +427,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -470,7 +470,7 @@ async def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectKeyV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectKeyV1Response, # type: ignore object_=_response.json(), ), @@ -481,7 +481,7 @@ async def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/members/invites/raw_client.py b/src/deepgram/manage/v1/projects/members/invites/raw_client.py index d7dce374..05824c5d 100644 --- a/src/deepgram/manage/v1/projects/members/invites/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/invites/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.create_project_invite_v1response import CreateProjectInviteV1Response from ......types.delete_project_invite_v1response import DeleteProjectInviteV1Response @@ -51,7 +51,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectInvitesV1Response, - parse_obj_as( + construct_type( type_=ListProjectInvitesV1Response, # type: ignore object_=_response.json(), ), @@ -62,7 +62,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -116,7 +116,7 @@ def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateProjectInviteV1Response, - parse_obj_as( + construct_type( type_=CreateProjectInviteV1Response, # type: ignore object_=_response.json(), ), @@ -127,7 +127,7 @@ def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -170,7 +170,7 @@ def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectInviteV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectInviteV1Response, # type: ignore object_=_response.json(), ), @@ -181,7 +181,7 @@ def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -226,7 +226,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectInvitesV1Response, - parse_obj_as( + construct_type( type_=ListProjectInvitesV1Response, # type: ignore object_=_response.json(), ), @@ -237,7 +237,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -291,7 +291,7 @@ async def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateProjectInviteV1Response, - parse_obj_as( + construct_type( type_=CreateProjectInviteV1Response, # type: ignore object_=_response.json(), ), @@ -302,7 +302,7 @@ async def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -345,7 +345,7 @@ async def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectInviteV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectInviteV1Response, # type: ignore object_=_response.json(), ), @@ -356,7 +356,7 @@ async def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/members/raw_client.py b/src/deepgram/manage/v1/projects/members/raw_client.py index fa671c6b..b72c342d 100644 --- a/src/deepgram/manage/v1/projects/members/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/raw_client.py @@ -7,8 +7,8 @@ from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as from .....core.request_options import RequestOptions +from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError from .....types.delete_project_member_v1response import DeleteProjectMemberV1Response from .....types.list_project_members_v1response import ListProjectMembersV1Response @@ -47,7 +47,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectMembersV1Response, - parse_obj_as( + construct_type( type_=ListProjectMembersV1Response, # type: ignore object_=_response.json(), ), @@ -58,7 +58,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -101,7 +101,7 @@ def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectMemberV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectMemberV1Response, # type: ignore object_=_response.json(), ), @@ -112,7 +112,7 @@ def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -157,7 +157,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectMembersV1Response, - parse_obj_as( + construct_type( type_=ListProjectMembersV1Response, # type: ignore object_=_response.json(), ), @@ -168,7 +168,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -211,7 +211,7 @@ async def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectMemberV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectMemberV1Response, # type: ignore object_=_response.json(), ), @@ -222,7 +222,7 @@ async def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/members/scopes/raw_client.py b/src/deepgram/manage/v1/projects/members/scopes/raw_client.py index 2cbfe030..6645527c 100644 --- a/src/deepgram/manage/v1/projects/members/scopes/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/scopes/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.list_project_member_scopes_v1response import ListProjectMemberScopesV1Response from ......types.update_project_member_scopes_v1response import UpdateProjectMemberScopesV1Response @@ -53,7 +53,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectMemberScopesV1Response, - parse_obj_as( + construct_type( type_=ListProjectMemberScopesV1Response, # type: ignore object_=_response.json(), ), @@ -64,7 +64,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -117,7 +117,7 @@ def update( if 200 <= _response.status_code < 300: _data = typing.cast( UpdateProjectMemberScopesV1Response, - parse_obj_as( + construct_type( type_=UpdateProjectMemberScopesV1Response, # type: ignore object_=_response.json(), ), @@ -128,7 +128,7 @@ def update( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -176,7 +176,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectMemberScopesV1Response, - parse_obj_as( + construct_type( type_=ListProjectMemberScopesV1Response, # type: ignore object_=_response.json(), ), @@ -187,7 +187,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -240,7 +240,7 @@ async def update( if 200 <= _response.status_code < 300: _data = typing.cast( UpdateProjectMemberScopesV1Response, - parse_obj_as( + construct_type( type_=UpdateProjectMemberScopesV1Response, # type: ignore object_=_response.json(), ), @@ -251,7 +251,7 @@ async def update( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/models/raw_client.py b/src/deepgram/manage/v1/projects/models/raw_client.py index 518870bf..fa9b7cde 100644 --- a/src/deepgram/manage/v1/projects/models/raw_client.py +++ b/src/deepgram/manage/v1/projects/models/raw_client.py @@ -7,8 +7,8 @@ from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as from .....core.request_options import RequestOptions +from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError from .....types.get_model_v1response import GetModelV1Response from .....types.list_models_v1response import ListModelsV1Response @@ -57,7 +57,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListModelsV1Response, - parse_obj_as( + construct_type( type_=ListModelsV1Response, # type: ignore object_=_response.json(), ), @@ -68,7 +68,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -111,7 +111,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetModelV1Response, - parse_obj_as( + construct_type( type_=GetModelV1Response, # type: ignore object_=_response.json(), ), @@ -122,7 +122,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -177,7 +177,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListModelsV1Response, - parse_obj_as( + construct_type( type_=ListModelsV1Response, # type: ignore object_=_response.json(), ), @@ -188,7 +188,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -231,7 +231,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetModelV1Response, - parse_obj_as( + construct_type( type_=GetModelV1Response, # type: ignore object_=_response.json(), ), @@ -242,7 +242,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/raw_client.py b/src/deepgram/manage/v1/projects/raw_client.py index bdcc7fbd..05afa3c9 100644 --- a/src/deepgram/manage/v1/projects/raw_client.py +++ b/src/deepgram/manage/v1/projects/raw_client.py @@ -7,8 +7,8 @@ from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse from ....core.jsonable_encoder import jsonable_encoder -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from ....types.delete_project_v1response import DeleteProjectV1Response from ....types.get_project_v1response import GetProjectV1Response @@ -48,7 +48,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectsV1Response, - parse_obj_as( + construct_type( type_=ListProjectsV1Response, # type: ignore object_=_response.json(), ), @@ -59,7 +59,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -114,7 +114,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectV1Response, - parse_obj_as( + construct_type( type_=GetProjectV1Response, # type: ignore object_=_response.json(), ), @@ -125,7 +125,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -165,7 +165,7 @@ def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectV1Response, # type: ignore object_=_response.json(), ), @@ -176,7 +176,7 @@ def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -230,7 +230,7 @@ def update( if 200 <= _response.status_code < 300: _data = typing.cast( UpdateProjectV1Response, - parse_obj_as( + construct_type( type_=UpdateProjectV1Response, # type: ignore object_=_response.json(), ), @@ -241,7 +241,7 @@ def update( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -281,7 +281,7 @@ def leave( if 200 <= _response.status_code < 300: _data = typing.cast( LeaveProjectV1Response, - parse_obj_as( + construct_type( type_=LeaveProjectV1Response, # type: ignore object_=_response.json(), ), @@ -292,7 +292,7 @@ def leave( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -334,7 +334,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectsV1Response, - parse_obj_as( + construct_type( type_=ListProjectsV1Response, # type: ignore object_=_response.json(), ), @@ -345,7 +345,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -400,7 +400,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectV1Response, - parse_obj_as( + construct_type( type_=GetProjectV1Response, # type: ignore object_=_response.json(), ), @@ -411,7 +411,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -451,7 +451,7 @@ async def delete( if 200 <= _response.status_code < 300: _data = typing.cast( DeleteProjectV1Response, - parse_obj_as( + construct_type( type_=DeleteProjectV1Response, # type: ignore object_=_response.json(), ), @@ -462,7 +462,7 @@ async def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -516,7 +516,7 @@ async def update( if 200 <= _response.status_code < 300: _data = typing.cast( UpdateProjectV1Response, - parse_obj_as( + construct_type( type_=UpdateProjectV1Response, # type: ignore object_=_response.json(), ), @@ -527,7 +527,7 @@ async def update( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -567,7 +567,7 @@ async def leave( if 200 <= _response.status_code < 300: _data = typing.cast( LeaveProjectV1Response, - parse_obj_as( + construct_type( type_=LeaveProjectV1Response, # type: ignore object_=_response.json(), ), @@ -578,7 +578,7 @@ async def leave( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/requests/raw_client.py b/src/deepgram/manage/v1/projects/requests/raw_client.py index e71b5f56..65befe11 100644 --- a/src/deepgram/manage/v1/projects/requests/raw_client.py +++ b/src/deepgram/manage/v1/projects/requests/raw_client.py @@ -9,8 +9,8 @@ from .....core.datetime_utils import serialize_datetime from .....core.http_response import AsyncHttpResponse, HttpResponse from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as from .....core.request_options import RequestOptions +from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError from .....types.get_project_request_v1response import GetProjectRequestV1Response from .....types.list_project_requests_v1response import ListProjectRequestsV1Response @@ -108,7 +108,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectRequestsV1Response, - parse_obj_as( + construct_type( type_=ListProjectRequestsV1Response, # type: ignore object_=_response.json(), ), @@ -119,7 +119,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -162,7 +162,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectRequestV1Response, - parse_obj_as( + construct_type( type_=GetProjectRequestV1Response, # type: ignore object_=_response.json(), ), @@ -173,7 +173,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -273,7 +273,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectRequestsV1Response, - parse_obj_as( + construct_type( type_=ListProjectRequestsV1Response, # type: ignore object_=_response.json(), ), @@ -284,7 +284,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -327,7 +327,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectRequestV1Response, - parse_obj_as( + construct_type( type_=GetProjectRequestV1Response, # type: ignore object_=_response.json(), ), @@ -338,7 +338,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py b/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py index 13e4a1b5..9e6788a8 100644 --- a/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.usage_breakdown_v1response import UsageBreakdownV1Response from .types.breakdown_get_request_deployment import BreakdownGetRequestDeployment @@ -280,7 +280,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( UsageBreakdownV1Response, - parse_obj_as( + construct_type( type_=UsageBreakdownV1Response, # type: ignore object_=_response.json(), ), @@ -291,7 +291,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -566,7 +566,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( UsageBreakdownV1Response, - parse_obj_as( + construct_type( type_=UsageBreakdownV1Response, # type: ignore object_=_response.json(), ), @@ -577,7 +577,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/usage/fields/raw_client.py b/src/deepgram/manage/v1/projects/usage/fields/raw_client.py index e80b6fa0..275f485a 100644 --- a/src/deepgram/manage/v1/projects/usage/fields/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/fields/raw_client.py @@ -7,8 +7,8 @@ from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse from ......core.jsonable_encoder import jsonable_encoder -from ......core.pydantic_utilities import parse_obj_as from ......core.request_options import RequestOptions +from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError from ......types.usage_fields_v1response import UsageFieldsV1Response @@ -61,7 +61,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( UsageFieldsV1Response, - parse_obj_as( + construct_type( type_=UsageFieldsV1Response, # type: ignore object_=_response.json(), ), @@ -72,7 +72,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -132,7 +132,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( UsageFieldsV1Response, - parse_obj_as( + construct_type( type_=UsageFieldsV1Response, # type: ignore object_=_response.json(), ), @@ -143,7 +143,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/manage/v1/projects/usage/raw_client.py b/src/deepgram/manage/v1/projects/usage/raw_client.py index 15077e42..c8a6e3a3 100644 --- a/src/deepgram/manage/v1/projects/usage/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/raw_client.py @@ -7,8 +7,8 @@ from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as from .....core.request_options import RequestOptions +from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError from .....types.usage_v1response import UsageV1Response from .types.usage_get_request_deployment import UsageGetRequestDeployment @@ -274,7 +274,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( UsageV1Response, - parse_obj_as( + construct_type( type_=UsageV1Response, # type: ignore object_=_response.json(), ), @@ -285,7 +285,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -555,7 +555,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( UsageV1Response, - parse_obj_as( + construct_type( type_=UsageV1Response, # type: ignore object_=_response.json(), ), @@ -566,7 +566,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/read/v1/text/raw_client.py b/src/deepgram/read/v1/text/raw_client.py index cdfc5f32..65b7ebca 100644 --- a/src/deepgram/read/v1/text/raw_client.py +++ b/src/deepgram/read/v1/text/raw_client.py @@ -6,9 +6,9 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions from ....core.serialization import convert_and_respect_annotation_metadata +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from ....requests.read_v1request import ReadV1RequestParams from ....types.read_v1response import ReadV1Response @@ -125,7 +125,7 @@ def analyze( if 200 <= _response.status_code < 300: _data = typing.cast( ReadV1Response, - parse_obj_as( + construct_type( type_=ReadV1Response, # type: ignore object_=_response.json(), ), @@ -136,7 +136,7 @@ def analyze( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -252,7 +252,7 @@ async def analyze( if 200 <= _response.status_code < 300: _data = typing.cast( ReadV1Response, - parse_obj_as( + construct_type( type_=ReadV1Response, # type: ignore object_=_response.json(), ), @@ -263,7 +263,7 @@ async def analyze( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py b/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py index 57b43ff8..f7e60ef9 100644 --- a/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py +++ b/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py @@ -7,8 +7,8 @@ from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse from ....core.jsonable_encoder import jsonable_encoder -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from ....types.create_project_distribution_credentials_v1response import CreateProjectDistributionCredentialsV1Response from ....types.get_project_distribution_credentials_v1response import GetProjectDistributionCredentialsV1Response @@ -52,7 +52,7 @@ def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=ListProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -63,7 +63,7 @@ def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -134,7 +134,7 @@ def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=CreateProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -145,7 +145,7 @@ def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -192,7 +192,7 @@ def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=GetProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -203,7 +203,7 @@ def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -250,7 +250,7 @@ def delete( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=GetProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -261,7 +261,7 @@ def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -306,7 +306,7 @@ async def list( if 200 <= _response.status_code < 300: _data = typing.cast( ListProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=ListProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -317,7 +317,7 @@ async def list( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -388,7 +388,7 @@ async def create( if 200 <= _response.status_code < 300: _data = typing.cast( CreateProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=CreateProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -399,7 +399,7 @@ async def create( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -446,7 +446,7 @@ async def get( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=GetProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -457,7 +457,7 @@ async def get( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -504,7 +504,7 @@ async def delete( if 200 <= _response.status_code < 300: _data = typing.cast( GetProjectDistributionCredentialsV1Response, - parse_obj_as( + construct_type( type_=GetProjectDistributionCredentialsV1Response, # type: ignore object_=_response.json(), ), @@ -515,7 +515,7 @@ async def delete( headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/speak/v1/audio/raw_client.py b/src/deepgram/speak/v1/audio/raw_client.py index 425c2daf..641512af 100644 --- a/src/deepgram/speak/v1/audio/raw_client.py +++ b/src/deepgram/speak/v1/audio/raw_client.py @@ -7,8 +7,8 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.pydantic_utilities import parse_obj_as from ....core.request_options import RequestOptions +from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError from .types.audio_generate_request_callback_method import AudioGenerateRequestCallbackMethod from .types.audio_generate_request_container import AudioGenerateRequestContainer @@ -120,7 +120,7 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), @@ -238,7 +238,7 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: headers=dict(_response.headers), body=typing.cast( typing.Any, - parse_obj_as( + construct_type( type_=typing.Any, # type: ignore object_=_response.json(), ), diff --git a/src/deepgram/speak/v1/types/speak_v1clear.py b/src/deepgram/speak/v1/types/speak_v1clear.py index b528050a..8a40e3c0 100644 --- a/src/deepgram/speak/v1/types/speak_v1clear.py +++ b/src/deepgram/speak/v1/types/speak_v1clear.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .speak_v1clear_type import SpeakV1ClearType -class SpeakV1Clear(UniversalBaseModel): +class SpeakV1Clear(UncheckedBaseModel): type: SpeakV1ClearType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1cleared.py b/src/deepgram/speak/v1/types/speak_v1cleared.py index 9e88c530..06328648 100644 --- a/src/deepgram/speak/v1/types/speak_v1cleared.py +++ b/src/deepgram/speak/v1/types/speak_v1cleared.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .speak_v1cleared_type import SpeakV1ClearedType -class SpeakV1Cleared(UniversalBaseModel): +class SpeakV1Cleared(UncheckedBaseModel): type: SpeakV1ClearedType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1close.py b/src/deepgram/speak/v1/types/speak_v1close.py index f801dc92..6e2e0d82 100644 --- a/src/deepgram/speak/v1/types/speak_v1close.py +++ b/src/deepgram/speak/v1/types/speak_v1close.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .speak_v1close_type import SpeakV1CloseType -class SpeakV1Close(UniversalBaseModel): +class SpeakV1Close(UncheckedBaseModel): type: SpeakV1CloseType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1flush.py b/src/deepgram/speak/v1/types/speak_v1flush.py index bfa3f72c..b9f6fa4d 100644 --- a/src/deepgram/speak/v1/types/speak_v1flush.py +++ b/src/deepgram/speak/v1/types/speak_v1flush.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .speak_v1flush_type import SpeakV1FlushType -class SpeakV1Flush(UniversalBaseModel): +class SpeakV1Flush(UncheckedBaseModel): type: SpeakV1FlushType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1flushed.py b/src/deepgram/speak/v1/types/speak_v1flushed.py index 6a5fd2c2..b1e4b127 100644 --- a/src/deepgram/speak/v1/types/speak_v1flushed.py +++ b/src/deepgram/speak/v1/types/speak_v1flushed.py @@ -3,11 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel from .speak_v1flushed_type import SpeakV1FlushedType -class SpeakV1Flushed(UniversalBaseModel): +class SpeakV1Flushed(UncheckedBaseModel): type: SpeakV1FlushedType = pydantic.Field() """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1metadata.py b/src/deepgram/speak/v1/types/speak_v1metadata.py index 4502f0c6..e009a764 100644 --- a/src/deepgram/speak/v1/types/speak_v1metadata.py +++ b/src/deepgram/speak/v1/types/speak_v1metadata.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class SpeakV1Metadata(UniversalBaseModel): +class SpeakV1Metadata(UncheckedBaseModel): type: typing.Literal["Metadata"] = pydantic.Field(default="Metadata") """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1text.py b/src/deepgram/speak/v1/types/speak_v1text.py index 94ec70c8..3a566770 100644 --- a/src/deepgram/speak/v1/types/speak_v1text.py +++ b/src/deepgram/speak/v1/types/speak_v1text.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class SpeakV1Text(UniversalBaseModel): +class SpeakV1Text(UncheckedBaseModel): type: typing.Literal["Speak"] = pydantic.Field(default="Speak") """ Message type identifier diff --git a/src/deepgram/speak/v1/types/speak_v1warning.py b/src/deepgram/speak/v1/types/speak_v1warning.py index 95815596..af374191 100644 --- a/src/deepgram/speak/v1/types/speak_v1warning.py +++ b/src/deepgram/speak/v1/types/speak_v1warning.py @@ -3,10 +3,11 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel -class SpeakV1Warning(UniversalBaseModel): +class SpeakV1Warning(UncheckedBaseModel): type: typing.Literal["Warning"] = pydantic.Field(default="Warning") """ Message type identifier diff --git a/src/deepgram/types/agent_think_models_v1response.py b/src/deepgram/types/agent_think_models_v1response.py index 1ed58066..f25bb4bd 100644 --- a/src/deepgram/types/agent_think_models_v1response.py +++ b/src/deepgram/types/agent_think_models_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .agent_think_models_v1response_models_item import AgentThinkModelsV1ResponseModelsItem -class AgentThinkModelsV1Response(UniversalBaseModel): +class AgentThinkModelsV1Response(UncheckedBaseModel): models: typing.List[AgentThinkModelsV1ResponseModelsItem] if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/agent_think_models_v1response_models_item_id.py b/src/deepgram/types/agent_think_models_v1response_models_item_id.py index 958ce5de..e203c954 100644 --- a/src/deepgram/types/agent_think_models_v1response_models_item_id.py +++ b/src/deepgram/types/agent_think_models_v1response_models_item_id.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class AgentThinkModelsV1ResponseModelsItemId(UniversalBaseModel): +class AgentThinkModelsV1ResponseModelsItemId(UncheckedBaseModel): """ AWS Bedrock models (custom models accepted) """ diff --git a/src/deepgram/types/agent_think_models_v1response_models_item_one.py b/src/deepgram/types/agent_think_models_v1response_models_item_one.py index 3678c590..63981a6d 100644 --- a/src/deepgram/types/agent_think_models_v1response_models_item_one.py +++ b/src/deepgram/types/agent_think_models_v1response_models_item_one.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .agent_think_models_v1response_models_item_one_id import AgentThinkModelsV1ResponseModelsItemOneId -class AgentThinkModelsV1ResponseModelsItemOne(UniversalBaseModel): +class AgentThinkModelsV1ResponseModelsItemOne(UncheckedBaseModel): """ Anthropic models """ diff --git a/src/deepgram/types/agent_think_models_v1response_models_item_three.py b/src/deepgram/types/agent_think_models_v1response_models_item_three.py index 45eaeb0e..2e8118f9 100644 --- a/src/deepgram/types/agent_think_models_v1response_models_item_three.py +++ b/src/deepgram/types/agent_think_models_v1response_models_item_three.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class AgentThinkModelsV1ResponseModelsItemThree(UniversalBaseModel): +class AgentThinkModelsV1ResponseModelsItemThree(UncheckedBaseModel): """ Groq models """ diff --git a/src/deepgram/types/agent_think_models_v1response_models_item_two.py b/src/deepgram/types/agent_think_models_v1response_models_item_two.py index 38d637fd..97e3f604 100644 --- a/src/deepgram/types/agent_think_models_v1response_models_item_two.py +++ b/src/deepgram/types/agent_think_models_v1response_models_item_two.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .agent_think_models_v1response_models_item_two_id import AgentThinkModelsV1ResponseModelsItemTwoId -class AgentThinkModelsV1ResponseModelsItemTwo(UniversalBaseModel): +class AgentThinkModelsV1ResponseModelsItemTwo(UncheckedBaseModel): """ Google models """ diff --git a/src/deepgram/types/agent_think_models_v1response_models_item_zero.py b/src/deepgram/types/agent_think_models_v1response_models_item_zero.py index f310645d..28850db2 100644 --- a/src/deepgram/types/agent_think_models_v1response_models_item_zero.py +++ b/src/deepgram/types/agent_think_models_v1response_models_item_zero.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .agent_think_models_v1response_models_item_zero_id import AgentThinkModelsV1ResponseModelsItemZeroId -class AgentThinkModelsV1ResponseModelsItemZero(UniversalBaseModel): +class AgentThinkModelsV1ResponseModelsItemZero(UncheckedBaseModel): """ OpenAI models """ diff --git a/src/deepgram/types/anthropic.py b/src/deepgram/types/anthropic.py index a8e3e1bc..c972254e 100644 --- a/src/deepgram/types/anthropic.py +++ b/src/deepgram/types/anthropic.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .anthropic_think_provider_model import AnthropicThinkProviderModel -class Anthropic(UniversalBaseModel): +class Anthropic(UncheckedBaseModel): type: typing.Literal["anthropic"] = "anthropic" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/aws_bedrock_think_provider.py b/src/deepgram/types/aws_bedrock_think_provider.py index df7ab671..a601a278 100644 --- a/src/deepgram/types/aws_bedrock_think_provider.py +++ b/src/deepgram/types/aws_bedrock_think_provider.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .aws_bedrock_think_provider_credentials import AwsBedrockThinkProviderCredentials from .aws_bedrock_think_provider_model import AwsBedrockThinkProviderModel -class AwsBedrockThinkProvider(UniversalBaseModel): +class AwsBedrockThinkProvider(UncheckedBaseModel): type: typing.Literal["aws_bedrock"] = "aws_bedrock" model: AwsBedrockThinkProviderModel = pydantic.Field() """ diff --git a/src/deepgram/types/aws_bedrock_think_provider_credentials.py b/src/deepgram/types/aws_bedrock_think_provider_credentials.py index aa3f7cc6..c014d379 100644 --- a/src/deepgram/types/aws_bedrock_think_provider_credentials.py +++ b/src/deepgram/types/aws_bedrock_think_provider_credentials.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .aws_bedrock_think_provider_credentials_type import AwsBedrockThinkProviderCredentialsType -class AwsBedrockThinkProviderCredentials(UniversalBaseModel): +class AwsBedrockThinkProviderCredentials(UncheckedBaseModel): """ AWS credentials type (STS short-lived or IAM long-lived) """ diff --git a/src/deepgram/types/aws_polly_speak_provider.py b/src/deepgram/types/aws_polly_speak_provider.py index ae47cbed..9dfa46bd 100644 --- a/src/deepgram/types/aws_polly_speak_provider.py +++ b/src/deepgram/types/aws_polly_speak_provider.py @@ -3,13 +3,14 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .aws_polly_speak_provider_credentials import AwsPollySpeakProviderCredentials from .aws_polly_speak_provider_engine import AwsPollySpeakProviderEngine from .aws_polly_speak_provider_voice import AwsPollySpeakProviderVoice -class AwsPollySpeakProvider(UniversalBaseModel): +class AwsPollySpeakProvider(UncheckedBaseModel): type: typing.Literal["aws_polly"] = "aws_polly" voice: AwsPollySpeakProviderVoice = pydantic.Field() """ diff --git a/src/deepgram/types/aws_polly_speak_provider_credentials.py b/src/deepgram/types/aws_polly_speak_provider_credentials.py index a7f77b15..eca5defc 100644 --- a/src/deepgram/types/aws_polly_speak_provider_credentials.py +++ b/src/deepgram/types/aws_polly_speak_provider_credentials.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .aws_polly_speak_provider_credentials_type import AwsPollySpeakProviderCredentialsType -class AwsPollySpeakProviderCredentials(UniversalBaseModel): +class AwsPollySpeakProviderCredentials(UncheckedBaseModel): type: AwsPollySpeakProviderCredentialsType region: str access_key_id: str diff --git a/src/deepgram/types/billing_breakdown_v1response.py b/src/deepgram/types/billing_breakdown_v1response.py index fdf5e218..13c56214 100644 --- a/src/deepgram/types/billing_breakdown_v1response.py +++ b/src/deepgram/types/billing_breakdown_v1response.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .billing_breakdown_v1response_resolution import BillingBreakdownV1ResponseResolution from .billing_breakdown_v1response_results_item import BillingBreakdownV1ResponseResultsItem -class BillingBreakdownV1Response(UniversalBaseModel): +class BillingBreakdownV1Response(UncheckedBaseModel): start: str = pydantic.Field() """ Start date of the billing summmary period diff --git a/src/deepgram/types/billing_breakdown_v1response_resolution.py b/src/deepgram/types/billing_breakdown_v1response_resolution.py index dbc6ca7e..8344144f 100644 --- a/src/deepgram/types/billing_breakdown_v1response_resolution.py +++ b/src/deepgram/types/billing_breakdown_v1response_resolution.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class BillingBreakdownV1ResponseResolution(UniversalBaseModel): +class BillingBreakdownV1ResponseResolution(UncheckedBaseModel): units: str = pydantic.Field() """ Time unit for the resolution diff --git a/src/deepgram/types/billing_breakdown_v1response_results_item.py b/src/deepgram/types/billing_breakdown_v1response_results_item.py index bc9195a8..be401a25 100644 --- a/src/deepgram/types/billing_breakdown_v1response_results_item.py +++ b/src/deepgram/types/billing_breakdown_v1response_results_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .billing_breakdown_v1response_results_item_grouping import BillingBreakdownV1ResponseResultsItemGrouping -class BillingBreakdownV1ResponseResultsItem(UniversalBaseModel): +class BillingBreakdownV1ResponseResultsItem(UncheckedBaseModel): dollars: float = pydantic.Field() """ USD cost of the billing for this grouping diff --git a/src/deepgram/types/billing_breakdown_v1response_results_item_grouping.py b/src/deepgram/types/billing_breakdown_v1response_results_item_grouping.py index d8ba6d59..6b809f60 100644 --- a/src/deepgram/types/billing_breakdown_v1response_results_item_grouping.py +++ b/src/deepgram/types/billing_breakdown_v1response_results_item_grouping.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class BillingBreakdownV1ResponseResultsItemGrouping(UniversalBaseModel): +class BillingBreakdownV1ResponseResultsItemGrouping(UncheckedBaseModel): start: typing.Optional[str] = pydantic.Field(default=None) """ Start date for this group diff --git a/src/deepgram/types/cartesia.py b/src/deepgram/types/cartesia.py index f852c852..bb6778bd 100644 --- a/src/deepgram/types/cartesia.py +++ b/src/deepgram/types/cartesia.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .cartesia_speak_provider_model_id import CartesiaSpeakProviderModelId from .cartesia_speak_provider_voice import CartesiaSpeakProviderVoice -class Cartesia(UniversalBaseModel): +class Cartesia(UncheckedBaseModel): type: typing.Literal["cartesia"] = "cartesia" version: typing.Optional[typing.Literal["2025-03-17"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/cartesia_speak_provider_voice.py b/src/deepgram/types/cartesia_speak_provider_voice.py index d6b4c4f1..cfc897e7 100644 --- a/src/deepgram/types/cartesia_speak_provider_voice.py +++ b/src/deepgram/types/cartesia_speak_provider_voice.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class CartesiaSpeakProviderVoice(UniversalBaseModel): +class CartesiaSpeakProviderVoice(UncheckedBaseModel): mode: str = pydantic.Field() """ Cartesia voice mode diff --git a/src/deepgram/types/create_key_v1response.py b/src/deepgram/types/create_key_v1response.py index bbf5799f..dd5d9235 100644 --- a/src/deepgram/types/create_key_v1response.py +++ b/src/deepgram/types/create_key_v1response.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class CreateKeyV1Response(UniversalBaseModel): +class CreateKeyV1Response(UncheckedBaseModel): """ API key created """ diff --git a/src/deepgram/types/create_project_distribution_credentials_v1response.py b/src/deepgram/types/create_project_distribution_credentials_v1response.py index a02c5877..3b5fd454 100644 --- a/src/deepgram/types/create_project_distribution_credentials_v1response.py +++ b/src/deepgram/types/create_project_distribution_credentials_v1response.py @@ -3,7 +3,8 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .create_project_distribution_credentials_v1response_distribution_credentials import ( CreateProjectDistributionCredentialsV1ResponseDistributionCredentials, ) @@ -12,7 +13,7 @@ ) -class CreateProjectDistributionCredentialsV1Response(UniversalBaseModel): +class CreateProjectDistributionCredentialsV1Response(UncheckedBaseModel): member: CreateProjectDistributionCredentialsV1ResponseMember distribution_credentials: CreateProjectDistributionCredentialsV1ResponseDistributionCredentials diff --git a/src/deepgram/types/create_project_distribution_credentials_v1response_distribution_credentials.py b/src/deepgram/types/create_project_distribution_credentials_v1response_distribution_credentials.py index c17fd7e0..baa3a137 100644 --- a/src/deepgram/types/create_project_distribution_credentials_v1response_distribution_credentials.py +++ b/src/deepgram/types/create_project_distribution_credentials_v1response_distribution_credentials.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class CreateProjectDistributionCredentialsV1ResponseDistributionCredentials(UniversalBaseModel): +class CreateProjectDistributionCredentialsV1ResponseDistributionCredentials(UncheckedBaseModel): distribution_credentials_id: str = pydantic.Field() """ Unique identifier for the distribution credentials diff --git a/src/deepgram/types/create_project_distribution_credentials_v1response_member.py b/src/deepgram/types/create_project_distribution_credentials_v1response_member.py index fb7aa0a5..ca189b8d 100644 --- a/src/deepgram/types/create_project_distribution_credentials_v1response_member.py +++ b/src/deepgram/types/create_project_distribution_credentials_v1response_member.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class CreateProjectDistributionCredentialsV1ResponseMember(UniversalBaseModel): +class CreateProjectDistributionCredentialsV1ResponseMember(UncheckedBaseModel): member_id: str = pydantic.Field() """ Unique identifier for the member diff --git a/src/deepgram/types/create_project_invite_v1response.py b/src/deepgram/types/create_project_invite_v1response.py index 885768b7..1fae0dee 100644 --- a/src/deepgram/types/create_project_invite_v1response.py +++ b/src/deepgram/types/create_project_invite_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class CreateProjectInviteV1Response(UniversalBaseModel): +class CreateProjectInviteV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/deepgram.py b/src/deepgram/types/deepgram.py index 0dfa5ccb..e3cd5f74 100644 --- a/src/deepgram/types/deepgram.py +++ b/src/deepgram/types/deepgram.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .deepgram_speak_provider_model import DeepgramSpeakProviderModel -class Deepgram(UniversalBaseModel): +class Deepgram(UncheckedBaseModel): type: typing.Literal["deepgram"] = "deepgram" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/delete_project_invite_v1response.py b/src/deepgram/types/delete_project_invite_v1response.py index 18df6963..77698f54 100644 --- a/src/deepgram/types/delete_project_invite_v1response.py +++ b/src/deepgram/types/delete_project_invite_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class DeleteProjectInviteV1Response(UniversalBaseModel): +class DeleteProjectInviteV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/delete_project_key_v1response.py b/src/deepgram/types/delete_project_key_v1response.py index 76c031d7..3a235615 100644 --- a/src/deepgram/types/delete_project_key_v1response.py +++ b/src/deepgram/types/delete_project_key_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class DeleteProjectKeyV1Response(UniversalBaseModel): +class DeleteProjectKeyV1Response(UncheckedBaseModel): message: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/delete_project_member_v1response.py b/src/deepgram/types/delete_project_member_v1response.py index 69af4773..494a9191 100644 --- a/src/deepgram/types/delete_project_member_v1response.py +++ b/src/deepgram/types/delete_project_member_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class DeleteProjectMemberV1Response(UniversalBaseModel): +class DeleteProjectMemberV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/delete_project_v1response.py b/src/deepgram/types/delete_project_v1response.py index 1c1634bd..fce0c811 100644 --- a/src/deepgram/types/delete_project_v1response.py +++ b/src/deepgram/types/delete_project_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class DeleteProjectV1Response(UniversalBaseModel): +class DeleteProjectV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ Confirmation message diff --git a/src/deepgram/types/eleven_labs_speak_provider.py b/src/deepgram/types/eleven_labs_speak_provider.py index c741221f..070d7423 100644 --- a/src/deepgram/types/eleven_labs_speak_provider.py +++ b/src/deepgram/types/eleven_labs_speak_provider.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .eleven_labs_speak_provider_model_id import ElevenLabsSpeakProviderModelId -class ElevenLabsSpeakProvider(UniversalBaseModel): +class ElevenLabsSpeakProvider(UncheckedBaseModel): type: typing.Literal["eleven_labs"] = "eleven_labs" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/error_response_legacy_error.py b/src/deepgram/types/error_response_legacy_error.py index 8964e3f2..c8b491f3 100644 --- a/src/deepgram/types/error_response_legacy_error.py +++ b/src/deepgram/types/error_response_legacy_error.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ErrorResponseLegacyError(UniversalBaseModel): +class ErrorResponseLegacyError(UncheckedBaseModel): err_code: typing.Optional[str] = pydantic.Field(default=None) """ The error code diff --git a/src/deepgram/types/error_response_modern_error.py b/src/deepgram/types/error_response_modern_error.py index 046f27f8..4ab6425c 100644 --- a/src/deepgram/types/error_response_modern_error.py +++ b/src/deepgram/types/error_response_modern_error.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ErrorResponseModernError(UniversalBaseModel): +class ErrorResponseModernError(UncheckedBaseModel): category: typing.Optional[str] = pydantic.Field(default=None) """ The category of the error diff --git a/src/deepgram/types/get_model_v1response_batch.py b/src/deepgram/types/get_model_v1response_batch.py index 463d8eb9..e8322b01 100644 --- a/src/deepgram/types/get_model_v1response_batch.py +++ b/src/deepgram/types/get_model_v1response_batch.py @@ -4,11 +4,12 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 from ..core.serialization import FieldMetadata +from ..core.unchecked_base_model import UncheckedBaseModel -class GetModelV1ResponseBatch(UniversalBaseModel): +class GetModelV1ResponseBatch(UncheckedBaseModel): name: typing.Optional[str] = None canonical_name: typing.Optional[str] = None architecture: typing.Optional[str] = None diff --git a/src/deepgram/types/get_model_v1response_metadata.py b/src/deepgram/types/get_model_v1response_metadata.py index e499605c..eb601e24 100644 --- a/src/deepgram/types/get_model_v1response_metadata.py +++ b/src/deepgram/types/get_model_v1response_metadata.py @@ -4,12 +4,13 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 from ..core.serialization import FieldMetadata +from ..core.unchecked_base_model import UncheckedBaseModel from .get_model_v1response_metadata_metadata import GetModelV1ResponseMetadataMetadata -class GetModelV1ResponseMetadata(UniversalBaseModel): +class GetModelV1ResponseMetadata(UncheckedBaseModel): name: typing.Optional[str] = None canonical_name: typing.Optional[str] = None architecture: typing.Optional[str] = None diff --git a/src/deepgram/types/get_model_v1response_metadata_metadata.py b/src/deepgram/types/get_model_v1response_metadata_metadata.py index 2683671c..a8472c30 100644 --- a/src/deepgram/types/get_model_v1response_metadata_metadata.py +++ b/src/deepgram/types/get_model_v1response_metadata_metadata.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetModelV1ResponseMetadataMetadata(UniversalBaseModel): +class GetModelV1ResponseMetadataMetadata(UncheckedBaseModel): accent: typing.Optional[str] = None age: typing.Optional[str] = None color: typing.Optional[str] = None diff --git a/src/deepgram/types/get_project_balance_v1response.py b/src/deepgram/types/get_project_balance_v1response.py index 66626628..a4f9cdf1 100644 --- a/src/deepgram/types/get_project_balance_v1response.py +++ b/src/deepgram/types/get_project_balance_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetProjectBalanceV1Response(UniversalBaseModel): +class GetProjectBalanceV1Response(UncheckedBaseModel): balance_id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the balance diff --git a/src/deepgram/types/get_project_distribution_credentials_v1response.py b/src/deepgram/types/get_project_distribution_credentials_v1response.py index 473aa142..516646ee 100644 --- a/src/deepgram/types/get_project_distribution_credentials_v1response.py +++ b/src/deepgram/types/get_project_distribution_credentials_v1response.py @@ -3,14 +3,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .get_project_distribution_credentials_v1response_distribution_credentials import ( GetProjectDistributionCredentialsV1ResponseDistributionCredentials, ) from .get_project_distribution_credentials_v1response_member import GetProjectDistributionCredentialsV1ResponseMember -class GetProjectDistributionCredentialsV1Response(UniversalBaseModel): +class GetProjectDistributionCredentialsV1Response(UncheckedBaseModel): member: GetProjectDistributionCredentialsV1ResponseMember distribution_credentials: GetProjectDistributionCredentialsV1ResponseDistributionCredentials diff --git a/src/deepgram/types/get_project_distribution_credentials_v1response_distribution_credentials.py b/src/deepgram/types/get_project_distribution_credentials_v1response_distribution_credentials.py index d1c44fd9..58c78916 100644 --- a/src/deepgram/types/get_project_distribution_credentials_v1response_distribution_credentials.py +++ b/src/deepgram/types/get_project_distribution_credentials_v1response_distribution_credentials.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetProjectDistributionCredentialsV1ResponseDistributionCredentials(UniversalBaseModel): +class GetProjectDistributionCredentialsV1ResponseDistributionCredentials(UncheckedBaseModel): distribution_credentials_id: str = pydantic.Field() """ Unique identifier for the distribution credentials diff --git a/src/deepgram/types/get_project_distribution_credentials_v1response_member.py b/src/deepgram/types/get_project_distribution_credentials_v1response_member.py index d9d674a1..ee7781e0 100644 --- a/src/deepgram/types/get_project_distribution_credentials_v1response_member.py +++ b/src/deepgram/types/get_project_distribution_credentials_v1response_member.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetProjectDistributionCredentialsV1ResponseMember(UniversalBaseModel): +class GetProjectDistributionCredentialsV1ResponseMember(UncheckedBaseModel): member_id: str = pydantic.Field() """ Unique identifier for the member diff --git a/src/deepgram/types/get_project_key_v1response.py b/src/deepgram/types/get_project_key_v1response.py index cbc00543..4c85f2ec 100644 --- a/src/deepgram/types/get_project_key_v1response.py +++ b/src/deepgram/types/get_project_key_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .get_project_key_v1response_item import GetProjectKeyV1ResponseItem -class GetProjectKeyV1Response(UniversalBaseModel): +class GetProjectKeyV1Response(UncheckedBaseModel): item: typing.Optional[GetProjectKeyV1ResponseItem] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/get_project_key_v1response_item.py b/src/deepgram/types/get_project_key_v1response_item.py index 37331fc3..076d9b2b 100644 --- a/src/deepgram/types/get_project_key_v1response_item.py +++ b/src/deepgram/types/get_project_key_v1response_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .get_project_key_v1response_item_member import GetProjectKeyV1ResponseItemMember -class GetProjectKeyV1ResponseItem(UniversalBaseModel): +class GetProjectKeyV1ResponseItem(UncheckedBaseModel): member: typing.Optional[GetProjectKeyV1ResponseItemMember] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/get_project_key_v1response_item_member.py b/src/deepgram/types/get_project_key_v1response_item_member.py index 4535d5b3..1b9aa3cf 100644 --- a/src/deepgram/types/get_project_key_v1response_item_member.py +++ b/src/deepgram/types/get_project_key_v1response_item_member.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .get_project_key_v1response_item_member_api_key import GetProjectKeyV1ResponseItemMemberApiKey -class GetProjectKeyV1ResponseItemMember(UniversalBaseModel): +class GetProjectKeyV1ResponseItemMember(UncheckedBaseModel): member_id: typing.Optional[str] = None email: typing.Optional[str] = None first_name: typing.Optional[str] = None diff --git a/src/deepgram/types/get_project_key_v1response_item_member_api_key.py b/src/deepgram/types/get_project_key_v1response_item_member_api_key.py index 44c7f78c..060c41f4 100644 --- a/src/deepgram/types/get_project_key_v1response_item_member_api_key.py +++ b/src/deepgram/types/get_project_key_v1response_item_member_api_key.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetProjectKeyV1ResponseItemMemberApiKey(UniversalBaseModel): +class GetProjectKeyV1ResponseItemMemberApiKey(UncheckedBaseModel): api_key_id: typing.Optional[str] = None comment: typing.Optional[str] = None scopes: typing.Optional[typing.List[str]] = None diff --git a/src/deepgram/types/get_project_request_v1response.py b/src/deepgram/types/get_project_request_v1response.py index 7bd48803..6eb17e74 100644 --- a/src/deepgram/types/get_project_request_v1response.py +++ b/src/deepgram/types/get_project_request_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .project_request_response import ProjectRequestResponse -class GetProjectRequestV1Response(UniversalBaseModel): +class GetProjectRequestV1Response(UncheckedBaseModel): request: typing.Optional[ProjectRequestResponse] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/get_project_v1response.py b/src/deepgram/types/get_project_v1response.py index a4b83fcb..9cde68a5 100644 --- a/src/deepgram/types/get_project_v1response.py +++ b/src/deepgram/types/get_project_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GetProjectV1Response(UniversalBaseModel): +class GetProjectV1Response(UncheckedBaseModel): project_id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the project diff --git a/src/deepgram/types/google.py b/src/deepgram/types/google.py index 14ad33ee..56e86997 100644 --- a/src/deepgram/types/google.py +++ b/src/deepgram/types/google.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .google_think_provider_model import GoogleThinkProviderModel -class Google(UniversalBaseModel): +class Google(UncheckedBaseModel): type: typing.Literal["google"] = "google" version: typing.Optional[typing.Literal["v1beta"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/grant_v1response.py b/src/deepgram/types/grant_v1response.py index 16507947..35b31a82 100644 --- a/src/deepgram/types/grant_v1response.py +++ b/src/deepgram/types/grant_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class GrantV1Response(UniversalBaseModel): +class GrantV1Response(UncheckedBaseModel): access_token: str = pydantic.Field() """ JSON Web Token (JWT) diff --git a/src/deepgram/types/groq.py b/src/deepgram/types/groq.py index ff765cc3..b04ae473 100644 --- a/src/deepgram/types/groq.py +++ b/src/deepgram/types/groq.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class Groq(UniversalBaseModel): +class Groq(UncheckedBaseModel): type: typing.Literal["groq"] = "groq" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/leave_project_v1response.py b/src/deepgram/types/leave_project_v1response.py index 92b61e9a..f4cadda7 100644 --- a/src/deepgram/types/leave_project_v1response.py +++ b/src/deepgram/types/leave_project_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class LeaveProjectV1Response(UniversalBaseModel): +class LeaveProjectV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/list_billing_fields_v1response.py b/src/deepgram/types/list_billing_fields_v1response.py index 3e35b2a3..86f0ec3b 100644 --- a/src/deepgram/types/list_billing_fields_v1response.py +++ b/src/deepgram/types/list_billing_fields_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_billing_fields_v1response_deployments_item import ListBillingFieldsV1ResponseDeploymentsItem -class ListBillingFieldsV1Response(UniversalBaseModel): +class ListBillingFieldsV1Response(UncheckedBaseModel): accessors: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ List of accessor UUIDs for the time period diff --git a/src/deepgram/types/list_models_v1response.py b/src/deepgram/types/list_models_v1response.py index acb22707..d3e49a19 100644 --- a/src/deepgram/types/list_models_v1response.py +++ b/src/deepgram/types/list_models_v1response.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_models_v1response_stt_models import ListModelsV1ResponseSttModels from .list_models_v1response_tts_models import ListModelsV1ResponseTtsModels -class ListModelsV1Response(UniversalBaseModel): +class ListModelsV1Response(UncheckedBaseModel): stt: typing.Optional[typing.List[ListModelsV1ResponseSttModels]] = None tts: typing.Optional[typing.List[ListModelsV1ResponseTtsModels]] = None diff --git a/src/deepgram/types/list_models_v1response_stt_models.py b/src/deepgram/types/list_models_v1response_stt_models.py index 34876d82..6028ff02 100644 --- a/src/deepgram/types/list_models_v1response_stt_models.py +++ b/src/deepgram/types/list_models_v1response_stt_models.py @@ -4,11 +4,12 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 from ..core.serialization import FieldMetadata +from ..core.unchecked_base_model import UncheckedBaseModel -class ListModelsV1ResponseSttModels(UniversalBaseModel): +class ListModelsV1ResponseSttModels(UncheckedBaseModel): name: typing.Optional[str] = None canonical_name: typing.Optional[str] = None architecture: typing.Optional[str] = None diff --git a/src/deepgram/types/list_models_v1response_tts_models.py b/src/deepgram/types/list_models_v1response_tts_models.py index b20e1a29..2d2600d8 100644 --- a/src/deepgram/types/list_models_v1response_tts_models.py +++ b/src/deepgram/types/list_models_v1response_tts_models.py @@ -4,12 +4,13 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 from ..core.serialization import FieldMetadata +from ..core.unchecked_base_model import UncheckedBaseModel from .list_models_v1response_tts_models_metadata import ListModelsV1ResponseTtsModelsMetadata -class ListModelsV1ResponseTtsModels(UniversalBaseModel): +class ListModelsV1ResponseTtsModels(UncheckedBaseModel): name: typing.Optional[str] = None canonical_name: typing.Optional[str] = None architecture: typing.Optional[str] = None diff --git a/src/deepgram/types/list_models_v1response_tts_models_metadata.py b/src/deepgram/types/list_models_v1response_tts_models_metadata.py index 8fb73af0..97bdb8f6 100644 --- a/src/deepgram/types/list_models_v1response_tts_models_metadata.py +++ b/src/deepgram/types/list_models_v1response_tts_models_metadata.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListModelsV1ResponseTtsModelsMetadata(UniversalBaseModel): +class ListModelsV1ResponseTtsModelsMetadata(UncheckedBaseModel): accent: typing.Optional[str] = None age: typing.Optional[str] = None color: typing.Optional[str] = None diff --git a/src/deepgram/types/list_project_balances_v1response.py b/src/deepgram/types/list_project_balances_v1response.py index 77cfbf45..e5cb9d18 100644 --- a/src/deepgram/types/list_project_balances_v1response.py +++ b/src/deepgram/types/list_project_balances_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_balances_v1response_balances_item import ListProjectBalancesV1ResponseBalancesItem -class ListProjectBalancesV1Response(UniversalBaseModel): +class ListProjectBalancesV1Response(UncheckedBaseModel): balances: typing.Optional[typing.List[ListProjectBalancesV1ResponseBalancesItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_project_balances_v1response_balances_item.py b/src/deepgram/types/list_project_balances_v1response_balances_item.py index aa91860f..9f30c639 100644 --- a/src/deepgram/types/list_project_balances_v1response_balances_item.py +++ b/src/deepgram/types/list_project_balances_v1response_balances_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectBalancesV1ResponseBalancesItem(UniversalBaseModel): +class ListProjectBalancesV1ResponseBalancesItem(UncheckedBaseModel): balance_id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the balance diff --git a/src/deepgram/types/list_project_distribution_credentials_v1response.py b/src/deepgram/types/list_project_distribution_credentials_v1response.py index 53ade44c..c66c2498 100644 --- a/src/deepgram/types/list_project_distribution_credentials_v1response.py +++ b/src/deepgram/types/list_project_distribution_credentials_v1response.py @@ -3,13 +3,14 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_distribution_credentials_v1response_distribution_credentials_item import ( ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItem, ) -class ListProjectDistributionCredentialsV1Response(UniversalBaseModel): +class ListProjectDistributionCredentialsV1Response(UncheckedBaseModel): distribution_credentials: typing.Optional[ typing.List[ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItem] ] = pydantic.Field(default=None) diff --git a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item.py b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item.py index 2b285b86..6e0338c8 100644 --- a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item.py +++ b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item.py @@ -3,7 +3,8 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_distribution_credentials_v1response_distribution_credentials_item_distribution_credentials import ( ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemDistributionCredentials, ) @@ -12,7 +13,7 @@ ) -class ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItem(UniversalBaseModel): +class ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItem(UncheckedBaseModel): member: ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemMember distribution_credentials: ( ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemDistributionCredentials diff --git a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_distribution_credentials.py b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_distribution_credentials.py index e1ee22ae..ca87029a 100644 --- a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_distribution_credentials.py +++ b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_distribution_credentials.py @@ -4,11 +4,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel class ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemDistributionCredentials( - UniversalBaseModel + UncheckedBaseModel ): distribution_credentials_id: str = pydantic.Field() """ diff --git a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_member.py b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_member.py index 61643e6f..64f3f007 100644 --- a/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_member.py +++ b/src/deepgram/types/list_project_distribution_credentials_v1response_distribution_credentials_item_member.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemMember(UniversalBaseModel): +class ListProjectDistributionCredentialsV1ResponseDistributionCredentialsItemMember(UncheckedBaseModel): member_id: str = pydantic.Field() """ Unique identifier for the member diff --git a/src/deepgram/types/list_project_invites_v1response.py b/src/deepgram/types/list_project_invites_v1response.py index a258d59b..8e32a92e 100644 --- a/src/deepgram/types/list_project_invites_v1response.py +++ b/src/deepgram/types/list_project_invites_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_invites_v1response_invites_item import ListProjectInvitesV1ResponseInvitesItem -class ListProjectInvitesV1Response(UniversalBaseModel): +class ListProjectInvitesV1Response(UncheckedBaseModel): invites: typing.Optional[typing.List[ListProjectInvitesV1ResponseInvitesItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_project_invites_v1response_invites_item.py b/src/deepgram/types/list_project_invites_v1response_invites_item.py index 05d182f4..b5858bb2 100644 --- a/src/deepgram/types/list_project_invites_v1response_invites_item.py +++ b/src/deepgram/types/list_project_invites_v1response_invites_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectInvitesV1ResponseInvitesItem(UniversalBaseModel): +class ListProjectInvitesV1ResponseInvitesItem(UncheckedBaseModel): email: typing.Optional[str] = pydantic.Field(default=None) """ The email address of the invitee diff --git a/src/deepgram/types/list_project_keys_v1response.py b/src/deepgram/types/list_project_keys_v1response.py index 3f28a437..8fcf3b55 100644 --- a/src/deepgram/types/list_project_keys_v1response.py +++ b/src/deepgram/types/list_project_keys_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_keys_v1response_api_keys_item import ListProjectKeysV1ResponseApiKeysItem -class ListProjectKeysV1Response(UniversalBaseModel): +class ListProjectKeysV1Response(UncheckedBaseModel): api_keys: typing.Optional[typing.List[ListProjectKeysV1ResponseApiKeysItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_project_keys_v1response_api_keys_item.py b/src/deepgram/types/list_project_keys_v1response_api_keys_item.py index 31e152c3..0e6dfba8 100644 --- a/src/deepgram/types/list_project_keys_v1response_api_keys_item.py +++ b/src/deepgram/types/list_project_keys_v1response_api_keys_item.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_keys_v1response_api_keys_item_api_key import ListProjectKeysV1ResponseApiKeysItemApiKey from .list_project_keys_v1response_api_keys_item_member import ListProjectKeysV1ResponseApiKeysItemMember -class ListProjectKeysV1ResponseApiKeysItem(UniversalBaseModel): +class ListProjectKeysV1ResponseApiKeysItem(UncheckedBaseModel): member: typing.Optional[ListProjectKeysV1ResponseApiKeysItemMember] = None api_key: typing.Optional[ListProjectKeysV1ResponseApiKeysItemApiKey] = None diff --git a/src/deepgram/types/list_project_keys_v1response_api_keys_item_api_key.py b/src/deepgram/types/list_project_keys_v1response_api_keys_item_api_key.py index 14ec931d..6de6b17b 100644 --- a/src/deepgram/types/list_project_keys_v1response_api_keys_item_api_key.py +++ b/src/deepgram/types/list_project_keys_v1response_api_keys_item_api_key.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectKeysV1ResponseApiKeysItemApiKey(UniversalBaseModel): +class ListProjectKeysV1ResponseApiKeysItemApiKey(UncheckedBaseModel): api_key_id: typing.Optional[str] = None comment: typing.Optional[str] = None scopes: typing.Optional[typing.List[str]] = None diff --git a/src/deepgram/types/list_project_keys_v1response_api_keys_item_member.py b/src/deepgram/types/list_project_keys_v1response_api_keys_item_member.py index f2c1b0bf..f5423403 100644 --- a/src/deepgram/types/list_project_keys_v1response_api_keys_item_member.py +++ b/src/deepgram/types/list_project_keys_v1response_api_keys_item_member.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectKeysV1ResponseApiKeysItemMember(UniversalBaseModel): +class ListProjectKeysV1ResponseApiKeysItemMember(UncheckedBaseModel): member_id: typing.Optional[str] = None email: typing.Optional[str] = None diff --git a/src/deepgram/types/list_project_member_scopes_v1response.py b/src/deepgram/types/list_project_member_scopes_v1response.py index 16774080..83bdcfc4 100644 --- a/src/deepgram/types/list_project_member_scopes_v1response.py +++ b/src/deepgram/types/list_project_member_scopes_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectMemberScopesV1Response(UniversalBaseModel): +class ListProjectMemberScopesV1Response(UncheckedBaseModel): scopes: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ The API scopes of the member diff --git a/src/deepgram/types/list_project_members_v1response.py b/src/deepgram/types/list_project_members_v1response.py index 8d91c4b6..b9a98e7a 100644 --- a/src/deepgram/types/list_project_members_v1response.py +++ b/src/deepgram/types/list_project_members_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_members_v1response_members_item import ListProjectMembersV1ResponseMembersItem -class ListProjectMembersV1Response(UniversalBaseModel): +class ListProjectMembersV1Response(UncheckedBaseModel): members: typing.Optional[typing.List[ListProjectMembersV1ResponseMembersItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_project_members_v1response_members_item.py b/src/deepgram/types/list_project_members_v1response_members_item.py index 210ad9e0..745e4392 100644 --- a/src/deepgram/types/list_project_members_v1response_members_item.py +++ b/src/deepgram/types/list_project_members_v1response_members_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectMembersV1ResponseMembersItem(UniversalBaseModel): +class ListProjectMembersV1ResponseMembersItem(UncheckedBaseModel): member_id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the member diff --git a/src/deepgram/types/list_project_purchases_v1response.py b/src/deepgram/types/list_project_purchases_v1response.py index 76375422..763403ae 100644 --- a/src/deepgram/types/list_project_purchases_v1response.py +++ b/src/deepgram/types/list_project_purchases_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_project_purchases_v1response_orders_item import ListProjectPurchasesV1ResponseOrdersItem -class ListProjectPurchasesV1Response(UniversalBaseModel): +class ListProjectPurchasesV1Response(UncheckedBaseModel): orders: typing.Optional[typing.List[ListProjectPurchasesV1ResponseOrdersItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_project_purchases_v1response_orders_item.py b/src/deepgram/types/list_project_purchases_v1response_orders_item.py index e0216500..59114302 100644 --- a/src/deepgram/types/list_project_purchases_v1response_orders_item.py +++ b/src/deepgram/types/list_project_purchases_v1response_orders_item.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectPurchasesV1ResponseOrdersItem(UniversalBaseModel): +class ListProjectPurchasesV1ResponseOrdersItem(UncheckedBaseModel): order_id: typing.Optional[str] = None expiration: typing.Optional[dt.datetime] = None created: typing.Optional[dt.datetime] = None diff --git a/src/deepgram/types/list_project_requests_v1response.py b/src/deepgram/types/list_project_requests_v1response.py index c3165e52..d3b3a981 100644 --- a/src/deepgram/types/list_project_requests_v1response.py +++ b/src/deepgram/types/list_project_requests_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .project_request_response import ProjectRequestResponse -class ListProjectRequestsV1Response(UniversalBaseModel): +class ListProjectRequestsV1Response(UncheckedBaseModel): page: typing.Optional[float] = pydantic.Field(default=None) """ The page number of the paginated response diff --git a/src/deepgram/types/list_projects_v1response.py b/src/deepgram/types/list_projects_v1response.py index 598d5190..9395d700 100644 --- a/src/deepgram/types/list_projects_v1response.py +++ b/src/deepgram/types/list_projects_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .list_projects_v1response_projects_item import ListProjectsV1ResponseProjectsItem -class ListProjectsV1Response(UniversalBaseModel): +class ListProjectsV1Response(UncheckedBaseModel): projects: typing.Optional[typing.List[ListProjectsV1ResponseProjectsItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/list_projects_v1response_projects_item.py b/src/deepgram/types/list_projects_v1response_projects_item.py index 29f5c148..aee96491 100644 --- a/src/deepgram/types/list_projects_v1response_projects_item.py +++ b/src/deepgram/types/list_projects_v1response_projects_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListProjectsV1ResponseProjectsItem(UniversalBaseModel): +class ListProjectsV1ResponseProjectsItem(UncheckedBaseModel): project_id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the project diff --git a/src/deepgram/types/listen_v1accepted_response.py b/src/deepgram/types/listen_v1accepted_response.py index be768162..7bbaccb0 100644 --- a/src/deepgram/types/listen_v1accepted_response.py +++ b/src/deepgram/types/listen_v1accepted_response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1AcceptedResponse(UniversalBaseModel): +class ListenV1AcceptedResponse(UncheckedBaseModel): """ Accepted response for asynchronous transcription requests """ diff --git a/src/deepgram/types/listen_v1redact.py b/src/deepgram/types/listen_v1redact.py index 9187906c..7bf572f3 100644 --- a/src/deepgram/types/listen_v1redact.py +++ b/src/deepgram/types/listen_v1redact.py @@ -2,10 +2,6 @@ import typing -ListenV1Redact = typing.Optional[ - typing.Union[ - typing.Literal["true", "false", "pci", "numbers", "aggressive_numbers", "ssn"], - str, - typing.Sequence[str], - ] +ListenV1Redact = typing.Union[ + typing.Literal["true", "false", "pci", "numbers", "aggressive_numbers", "ssn"], typing.Any ] diff --git a/src/deepgram/types/listen_v1response.py b/src/deepgram/types/listen_v1response.py index 2ea01865..f19473ca 100644 --- a/src/deepgram/types/listen_v1response.py +++ b/src/deepgram/types/listen_v1response.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_metadata import ListenV1ResponseMetadata from .listen_v1response_results import ListenV1ResponseResults -class ListenV1Response(UniversalBaseModel): +class ListenV1Response(UncheckedBaseModel): """ The standard transcription response """ diff --git a/src/deepgram/types/listen_v1response_metadata.py b/src/deepgram/types/listen_v1response_metadata.py index 4a0463ee..02b40254 100644 --- a/src/deepgram/types/listen_v1response_metadata.py +++ b/src/deepgram/types/listen_v1response_metadata.py @@ -4,14 +4,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_metadata_intents_info import ListenV1ResponseMetadataIntentsInfo from .listen_v1response_metadata_sentiment_info import ListenV1ResponseMetadataSentimentInfo from .listen_v1response_metadata_summary_info import ListenV1ResponseMetadataSummaryInfo from .listen_v1response_metadata_topics_info import ListenV1ResponseMetadataTopicsInfo -class ListenV1ResponseMetadata(UniversalBaseModel): +class ListenV1ResponseMetadata(UncheckedBaseModel): transaction_key: typing.Optional[str] = None request_id: str sha256: str diff --git a/src/deepgram/types/listen_v1response_metadata_intents_info.py b/src/deepgram/types/listen_v1response_metadata_intents_info.py index 691d9d14..a470c0a7 100644 --- a/src/deepgram/types/listen_v1response_metadata_intents_info.py +++ b/src/deepgram/types/listen_v1response_metadata_intents_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseMetadataIntentsInfo(UniversalBaseModel): +class ListenV1ResponseMetadataIntentsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_metadata_sentiment_info.py b/src/deepgram/types/listen_v1response_metadata_sentiment_info.py index 57e0d995..a78f9cc2 100644 --- a/src/deepgram/types/listen_v1response_metadata_sentiment_info.py +++ b/src/deepgram/types/listen_v1response_metadata_sentiment_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseMetadataSentimentInfo(UniversalBaseModel): +class ListenV1ResponseMetadataSentimentInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_metadata_summary_info.py b/src/deepgram/types/listen_v1response_metadata_summary_info.py index 4e1977bc..7b4ea8ce 100644 --- a/src/deepgram/types/listen_v1response_metadata_summary_info.py +++ b/src/deepgram/types/listen_v1response_metadata_summary_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseMetadataSummaryInfo(UniversalBaseModel): +class ListenV1ResponseMetadataSummaryInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_metadata_topics_info.py b/src/deepgram/types/listen_v1response_metadata_topics_info.py index 5103969e..2569296b 100644 --- a/src/deepgram/types/listen_v1response_metadata_topics_info.py +++ b/src/deepgram/types/listen_v1response_metadata_topics_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseMetadataTopicsInfo(UniversalBaseModel): +class ListenV1ResponseMetadataTopicsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results.py b/src/deepgram/types/listen_v1response_results.py index 87612fb1..a99961ba 100644 --- a/src/deepgram/types/listen_v1response_results.py +++ b/src/deepgram/types/listen_v1response_results.py @@ -3,7 +3,8 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels import ListenV1ResponseResultsChannels from .listen_v1response_results_summary import ListenV1ResponseResultsSummary from .listen_v1response_results_utterances import ListenV1ResponseResultsUtterances @@ -12,7 +13,7 @@ from .shared_topics import SharedTopics -class ListenV1ResponseResults(UniversalBaseModel): +class ListenV1ResponseResults(UncheckedBaseModel): channels: ListenV1ResponseResultsChannels utterances: typing.Optional[ListenV1ResponseResultsUtterances] = None summary: typing.Optional[ListenV1ResponseResultsSummary] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item.py b/src/deepgram/types/listen_v1response_results_channels_item.py index 94fc53e8..de2a8493 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item.py @@ -3,14 +3,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels_item_alternatives_item import ( ListenV1ResponseResultsChannelsItemAlternativesItem, ) from .listen_v1response_results_channels_item_search_item import ListenV1ResponseResultsChannelsItemSearchItem -class ListenV1ResponseResultsChannelsItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItem(UncheckedBaseModel): search: typing.Optional[typing.List[ListenV1ResponseResultsChannelsItemSearchItem]] = None alternatives: typing.Optional[typing.List[ListenV1ResponseResultsChannelsItemAlternativesItem]] = None detected_language: typing.Optional[str] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item.py index ddf91b60..c7c96523 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item.py @@ -3,7 +3,8 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels_item_alternatives_item_entities_item import ( ListenV1ResponseResultsChannelsItemAlternativesItemEntitiesItem, ) @@ -21,7 +22,7 @@ ) -class ListenV1ResponseResultsChannelsItemAlternativesItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItem(UncheckedBaseModel): transcript: typing.Optional[str] = None confidence: typing.Optional[float] = None words: typing.Optional[typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemWordsItem]] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_entities_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_entities_item.py index 6fb26e5a..5dfbb4fb 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_entities_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_entities_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemAlternativesItemEntitiesItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemEntitiesItem(UncheckedBaseModel): label: typing.Optional[str] = None value: typing.Optional[str] = None raw_value: typing.Optional[str] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs.py index 8ca18dba..5c8eaf6a 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs.py @@ -3,13 +3,14 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item import ( ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItem, ) -class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphs(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphs(UncheckedBaseModel): transcript: typing.Optional[str] = None paragraphs: typing.Optional[ typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItem] diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py index d38e7e39..a622d4ae 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py @@ -3,18 +3,19 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item_sentences_item import ( ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem, ) -class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItem(UncheckedBaseModel): sentences: typing.Optional[ typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem] ] = None - speaker: typing.Optional[int] = None - num_words: typing.Optional[int] = None + speaker: typing.Optional[float] = None + num_words: typing.Optional[float] = None start: typing.Optional[float] = None end: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item_sentences_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item_sentences_item.py index 4c8d3bd7..54d9b1c0 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item_sentences_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item_sentences_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem(UncheckedBaseModel): text: typing.Optional[str] = None start: typing.Optional[float] = None end: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_summaries_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_summaries_item.py index fd7dd560..5c78e9ba 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_summaries_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_summaries_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemAlternativesItemSummariesItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemSummariesItem(UncheckedBaseModel): summary: typing.Optional[str] = None start_word: typing.Optional[float] = None end_word: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_topics_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_topics_item.py index 96b50627..23d63712 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_topics_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_topics_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemAlternativesItemTopicsItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemTopicsItem(UncheckedBaseModel): text: typing.Optional[str] = None start_word: typing.Optional[float] = None end_word: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_words_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_words_item.py index 72e343e8..c2b63fa5 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_words_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_words_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemAlternativesItemWordsItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemAlternativesItemWordsItem(UncheckedBaseModel): word: typing.Optional[str] = None start: typing.Optional[float] = None end: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_search_item.py b/src/deepgram/types/listen_v1response_results_channels_item_search_item.py index 1690c5fb..cec35356 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_search_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_search_item.py @@ -3,13 +3,14 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_channels_item_search_item_hits_item import ( ListenV1ResponseResultsChannelsItemSearchItemHitsItem, ) -class ListenV1ResponseResultsChannelsItemSearchItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemSearchItem(UncheckedBaseModel): query: typing.Optional[str] = None hits: typing.Optional[typing.List[ListenV1ResponseResultsChannelsItemSearchItemHitsItem]] = None diff --git a/src/deepgram/types/listen_v1response_results_channels_item_search_item_hits_item.py b/src/deepgram/types/listen_v1response_results_channels_item_search_item_hits_item.py index 7a12b2ea..0dd97f41 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_search_item_hits_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_search_item_hits_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsChannelsItemSearchItemHitsItem(UniversalBaseModel): +class ListenV1ResponseResultsChannelsItemSearchItemHitsItem(UncheckedBaseModel): confidence: typing.Optional[float] = None start: typing.Optional[float] = None end: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_summary.py b/src/deepgram/types/listen_v1response_results_summary.py index d76564fe..b71a7933 100644 --- a/src/deepgram/types/listen_v1response_results_summary.py +++ b/src/deepgram/types/listen_v1response_results_summary.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsSummary(UniversalBaseModel): +class ListenV1ResponseResultsSummary(UncheckedBaseModel): result: typing.Optional[str] = None short: typing.Optional[str] = None diff --git a/src/deepgram/types/listen_v1response_results_utterances_item.py b/src/deepgram/types/listen_v1response_results_utterances_item.py index a9ce5e77..ed8a8ddd 100644 --- a/src/deepgram/types/listen_v1response_results_utterances_item.py +++ b/src/deepgram/types/listen_v1response_results_utterances_item.py @@ -3,18 +3,19 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .listen_v1response_results_utterances_item_words_item import ListenV1ResponseResultsUtterancesItemWordsItem -class ListenV1ResponseResultsUtterancesItem(UniversalBaseModel): +class ListenV1ResponseResultsUtterancesItem(UncheckedBaseModel): start: typing.Optional[float] = None end: typing.Optional[float] = None confidence: typing.Optional[float] = None - channel: typing.Optional[int] = None + channel: typing.Optional[float] = None transcript: typing.Optional[str] = None words: typing.Optional[typing.List[ListenV1ResponseResultsUtterancesItemWordsItem]] = None - speaker: typing.Optional[int] = None + speaker: typing.Optional[float] = None id: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py index 7c3cfc84..716f2e2a 100644 --- a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py +++ b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py @@ -3,15 +3,16 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ListenV1ResponseResultsUtterancesItemWordsItem(UniversalBaseModel): +class ListenV1ResponseResultsUtterancesItemWordsItem(UncheckedBaseModel): word: typing.Optional[str] = None start: typing.Optional[float] = None end: typing.Optional[float] = None confidence: typing.Optional[float] = None - speaker: typing.Optional[int] = None + speaker: typing.Optional[float] = None speaker_confidence: typing.Optional[float] = None punctuated_word: typing.Optional[str] = None diff --git a/src/deepgram/types/open_ai_speak_provider.py b/src/deepgram/types/open_ai_speak_provider.py index f2eb02cb..204c2434 100644 --- a/src/deepgram/types/open_ai_speak_provider.py +++ b/src/deepgram/types/open_ai_speak_provider.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .open_ai_speak_provider_model import OpenAiSpeakProviderModel from .open_ai_speak_provider_voice import OpenAiSpeakProviderVoice -class OpenAiSpeakProvider(UniversalBaseModel): +class OpenAiSpeakProvider(UncheckedBaseModel): type: typing.Literal["open_ai"] = "open_ai" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/open_ai_think_provider.py b/src/deepgram/types/open_ai_think_provider.py index b19f7148..fd3e2601 100644 --- a/src/deepgram/types/open_ai_think_provider.py +++ b/src/deepgram/types/open_ai_think_provider.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .open_ai_think_provider_model import OpenAiThinkProviderModel -class OpenAiThinkProvider(UniversalBaseModel): +class OpenAiThinkProvider(UncheckedBaseModel): type: typing.Literal["open_ai"] = "open_ai" version: typing.Optional[typing.Literal["v1"]] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/project_request_response.py b/src/deepgram/types/project_request_response.py index fde3ca2d..bbd47ac4 100644 --- a/src/deepgram/types/project_request_response.py +++ b/src/deepgram/types/project_request_response.py @@ -4,10 +4,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ProjectRequestResponse(UniversalBaseModel): +class ProjectRequestResponse(UncheckedBaseModel): """ A single request """ diff --git a/src/deepgram/types/read_v1request_text.py b/src/deepgram/types/read_v1request_text.py index 11c16451..551ce439 100644 --- a/src/deepgram/types/read_v1request_text.py +++ b/src/deepgram/types/read_v1request_text.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1RequestText(UniversalBaseModel): +class ReadV1RequestText(UncheckedBaseModel): text: str = pydantic.Field() """ The plain text to analyze diff --git a/src/deepgram/types/read_v1request_url.py b/src/deepgram/types/read_v1request_url.py index 3483c469..fe7f6173 100644 --- a/src/deepgram/types/read_v1request_url.py +++ b/src/deepgram/types/read_v1request_url.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1RequestUrl(UniversalBaseModel): +class ReadV1RequestUrl(UncheckedBaseModel): url: str = pydantic.Field() """ A URL pointing to the text source diff --git a/src/deepgram/types/read_v1response.py b/src/deepgram/types/read_v1response.py index a0218a10..08536a25 100644 --- a/src/deepgram/types/read_v1response.py +++ b/src/deepgram/types/read_v1response.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_metadata import ReadV1ResponseMetadata from .read_v1response_results import ReadV1ResponseResults -class ReadV1Response(UniversalBaseModel): +class ReadV1Response(UncheckedBaseModel): """ The standard text response """ diff --git a/src/deepgram/types/read_v1response_metadata.py b/src/deepgram/types/read_v1response_metadata.py index 482ad5ae..9b3ebddd 100644 --- a/src/deepgram/types/read_v1response_metadata.py +++ b/src/deepgram/types/read_v1response_metadata.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_metadata_metadata import ReadV1ResponseMetadataMetadata -class ReadV1ResponseMetadata(UniversalBaseModel): +class ReadV1ResponseMetadata(UncheckedBaseModel): metadata: typing.Optional[ReadV1ResponseMetadataMetadata] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/read_v1response_metadata_metadata.py b/src/deepgram/types/read_v1response_metadata_metadata.py index 6f9eab06..e353d3fc 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata.py +++ b/src/deepgram/types/read_v1response_metadata_metadata.py @@ -4,14 +4,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_metadata_metadata_intents_info import ReadV1ResponseMetadataMetadataIntentsInfo from .read_v1response_metadata_metadata_sentiment_info import ReadV1ResponseMetadataMetadataSentimentInfo from .read_v1response_metadata_metadata_summary_info import ReadV1ResponseMetadataMetadataSummaryInfo from .read_v1response_metadata_metadata_topics_info import ReadV1ResponseMetadataMetadataTopicsInfo -class ReadV1ResponseMetadataMetadata(UniversalBaseModel): +class ReadV1ResponseMetadataMetadata(UncheckedBaseModel): request_id: typing.Optional[str] = None created: typing.Optional[dt.datetime] = None language: typing.Optional[str] = None diff --git a/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py b/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py index 5bbb2a5b..505c8115 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1ResponseMetadataMetadataIntentsInfo(UniversalBaseModel): +class ReadV1ResponseMetadataMetadataIntentsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py b/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py index 545ac29b..b54f7b06 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1ResponseMetadataMetadataSentimentInfo(UniversalBaseModel): +class ReadV1ResponseMetadataMetadataSentimentInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py b/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py index 3d0cfb55..2f6a91c7 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1ResponseMetadataMetadataSummaryInfo(UniversalBaseModel): +class ReadV1ResponseMetadataMetadataSummaryInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py b/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py index beea0590..8f413eb5 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1ResponseMetadataMetadataTopicsInfo(UniversalBaseModel): +class ReadV1ResponseMetadataMetadataTopicsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None input_tokens: typing.Optional[float] = None output_tokens: typing.Optional[float] = None diff --git a/src/deepgram/types/read_v1response_results.py b/src/deepgram/types/read_v1response_results.py index fe163c23..9fa99f21 100644 --- a/src/deepgram/types/read_v1response_results.py +++ b/src/deepgram/types/read_v1response_results.py @@ -3,14 +3,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_results_summary import ReadV1ResponseResultsSummary from .shared_intents import SharedIntents from .shared_sentiments import SharedSentiments from .shared_topics import SharedTopics -class ReadV1ResponseResults(UniversalBaseModel): +class ReadV1ResponseResults(UncheckedBaseModel): summary: typing.Optional[ReadV1ResponseResultsSummary] = None topics: typing.Optional[SharedTopics] = None intents: typing.Optional[SharedIntents] = None diff --git a/src/deepgram/types/read_v1response_results_summary.py b/src/deepgram/types/read_v1response_results_summary.py index ceab5de1..a39dc8ed 100644 --- a/src/deepgram/types/read_v1response_results_summary.py +++ b/src/deepgram/types/read_v1response_results_summary.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_results_summary_results import ReadV1ResponseResultsSummaryResults -class ReadV1ResponseResultsSummary(UniversalBaseModel): +class ReadV1ResponseResultsSummary(UncheckedBaseModel): """ Output whenever `summary=true` is used """ diff --git a/src/deepgram/types/read_v1response_results_summary_results.py b/src/deepgram/types/read_v1response_results_summary_results.py index 6e85dc69..c8885337 100644 --- a/src/deepgram/types/read_v1response_results_summary_results.py +++ b/src/deepgram/types/read_v1response_results_summary_results.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .read_v1response_results_summary_results_summary import ReadV1ResponseResultsSummaryResultsSummary -class ReadV1ResponseResultsSummaryResults(UniversalBaseModel): +class ReadV1ResponseResultsSummaryResults(UncheckedBaseModel): summary: typing.Optional[ReadV1ResponseResultsSummaryResultsSummary] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/read_v1response_results_summary_results_summary.py b/src/deepgram/types/read_v1response_results_summary_results_summary.py index 3f488461..e810721b 100644 --- a/src/deepgram/types/read_v1response_results_summary_results_summary.py +++ b/src/deepgram/types/read_v1response_results_summary_results_summary.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ReadV1ResponseResultsSummaryResultsSummary(UniversalBaseModel): +class ReadV1ResponseResultsSummaryResultsSummary(UncheckedBaseModel): text: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/shared_intents.py b/src/deepgram/types/shared_intents.py index 16106e0d..01aae29a 100644 --- a/src/deepgram/types/shared_intents.py +++ b/src/deepgram/types/shared_intents.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_intents_results import SharedIntentsResults -class SharedIntents(UniversalBaseModel): +class SharedIntents(UncheckedBaseModel): """ Output whenever `intents=true` is used """ diff --git a/src/deepgram/types/shared_intents_results.py b/src/deepgram/types/shared_intents_results.py index 9f86517e..a227c096 100644 --- a/src/deepgram/types/shared_intents_results.py +++ b/src/deepgram/types/shared_intents_results.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_intents_results_intents import SharedIntentsResultsIntents -class SharedIntentsResults(UniversalBaseModel): +class SharedIntentsResults(UncheckedBaseModel): intents: typing.Optional[SharedIntentsResultsIntents] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/shared_intents_results_intents.py b/src/deepgram/types/shared_intents_results_intents.py index 73976e28..4415cc73 100644 --- a/src/deepgram/types/shared_intents_results_intents.py +++ b/src/deepgram/types/shared_intents_results_intents.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_intents_results_intents_segments_item import SharedIntentsResultsIntentsSegmentsItem -class SharedIntentsResultsIntents(UniversalBaseModel): +class SharedIntentsResultsIntents(UncheckedBaseModel): segments: typing.Optional[typing.List[SharedIntentsResultsIntentsSegmentsItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/shared_intents_results_intents_segments_item.py b/src/deepgram/types/shared_intents_results_intents_segments_item.py index 7a869781..583b7f49 100644 --- a/src/deepgram/types/shared_intents_results_intents_segments_item.py +++ b/src/deepgram/types/shared_intents_results_intents_segments_item.py @@ -3,13 +3,14 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_intents_results_intents_segments_item_intents_item import ( SharedIntentsResultsIntentsSegmentsItemIntentsItem, ) -class SharedIntentsResultsIntentsSegmentsItem(UniversalBaseModel): +class SharedIntentsResultsIntentsSegmentsItem(UncheckedBaseModel): text: typing.Optional[str] = None start_word: typing.Optional[float] = None end_word: typing.Optional[float] = None diff --git a/src/deepgram/types/shared_intents_results_intents_segments_item_intents_item.py b/src/deepgram/types/shared_intents_results_intents_segments_item_intents_item.py index a0069cce..7b1fb0c5 100644 --- a/src/deepgram/types/shared_intents_results_intents_segments_item_intents_item.py +++ b/src/deepgram/types/shared_intents_results_intents_segments_item_intents_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class SharedIntentsResultsIntentsSegmentsItemIntentsItem(UniversalBaseModel): +class SharedIntentsResultsIntentsSegmentsItemIntentsItem(UncheckedBaseModel): intent: typing.Optional[str] = None confidence_score: typing.Optional[float] = None diff --git a/src/deepgram/types/shared_sentiments.py b/src/deepgram/types/shared_sentiments.py index e9296b19..ec600684 100644 --- a/src/deepgram/types/shared_sentiments.py +++ b/src/deepgram/types/shared_sentiments.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_sentiments_average import SharedSentimentsAverage from .shared_sentiments_segments_item import SharedSentimentsSegmentsItem -class SharedSentiments(UniversalBaseModel): +class SharedSentiments(UncheckedBaseModel): """ Output whenever `sentiment=true` is used """ diff --git a/src/deepgram/types/shared_sentiments_average.py b/src/deepgram/types/shared_sentiments_average.py index 5f5985e4..f14f6f8a 100644 --- a/src/deepgram/types/shared_sentiments_average.py +++ b/src/deepgram/types/shared_sentiments_average.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class SharedSentimentsAverage(UniversalBaseModel): +class SharedSentimentsAverage(UncheckedBaseModel): sentiment: typing.Optional[str] = None sentiment_score: typing.Optional[float] = None diff --git a/src/deepgram/types/shared_sentiments_segments_item.py b/src/deepgram/types/shared_sentiments_segments_item.py index a82de160..f96425fd 100644 --- a/src/deepgram/types/shared_sentiments_segments_item.py +++ b/src/deepgram/types/shared_sentiments_segments_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class SharedSentimentsSegmentsItem(UniversalBaseModel): +class SharedSentimentsSegmentsItem(UncheckedBaseModel): text: typing.Optional[str] = None start_word: typing.Optional[float] = None end_word: typing.Optional[float] = None diff --git a/src/deepgram/types/shared_topics.py b/src/deepgram/types/shared_topics.py index 07537bd0..2641bed6 100644 --- a/src/deepgram/types/shared_topics.py +++ b/src/deepgram/types/shared_topics.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_topics_results import SharedTopicsResults -class SharedTopics(UniversalBaseModel): +class SharedTopics(UncheckedBaseModel): """ Output whenever `topics=true` is used """ diff --git a/src/deepgram/types/shared_topics_results.py b/src/deepgram/types/shared_topics_results.py index 9b4aaf41..ec0f7574 100644 --- a/src/deepgram/types/shared_topics_results.py +++ b/src/deepgram/types/shared_topics_results.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_topics_results_topics import SharedTopicsResultsTopics -class SharedTopicsResults(UniversalBaseModel): +class SharedTopicsResults(UncheckedBaseModel): topics: typing.Optional[SharedTopicsResultsTopics] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/shared_topics_results_topics.py b/src/deepgram/types/shared_topics_results_topics.py index 081ec3da..3983e13a 100644 --- a/src/deepgram/types/shared_topics_results_topics.py +++ b/src/deepgram/types/shared_topics_results_topics.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_topics_results_topics_segments_item import SharedTopicsResultsTopicsSegmentsItem -class SharedTopicsResultsTopics(UniversalBaseModel): +class SharedTopicsResultsTopics(UncheckedBaseModel): segments: typing.Optional[typing.List[SharedTopicsResultsTopicsSegmentsItem]] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/shared_topics_results_topics_segments_item.py b/src/deepgram/types/shared_topics_results_topics_segments_item.py index 3bb5900c..884dc4c3 100644 --- a/src/deepgram/types/shared_topics_results_topics_segments_item.py +++ b/src/deepgram/types/shared_topics_results_topics_segments_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .shared_topics_results_topics_segments_item_topics_item import SharedTopicsResultsTopicsSegmentsItemTopicsItem -class SharedTopicsResultsTopicsSegmentsItem(UniversalBaseModel): +class SharedTopicsResultsTopicsSegmentsItem(UncheckedBaseModel): text: typing.Optional[str] = None start_word: typing.Optional[float] = None end_word: typing.Optional[float] = None diff --git a/src/deepgram/types/shared_topics_results_topics_segments_item_topics_item.py b/src/deepgram/types/shared_topics_results_topics_segments_item_topics_item.py index 735c4b3c..b2cf2d27 100644 --- a/src/deepgram/types/shared_topics_results_topics_segments_item_topics_item.py +++ b/src/deepgram/types/shared_topics_results_topics_segments_item_topics_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class SharedTopicsResultsTopicsSegmentsItemTopicsItem(UniversalBaseModel): +class SharedTopicsResultsTopicsSegmentsItemTopicsItem(UncheckedBaseModel): topic: typing.Optional[str] = None confidence_score: typing.Optional[float] = None diff --git a/src/deepgram/types/speak_settings_v1.py b/src/deepgram/types/speak_settings_v1.py index 77c62835..e4c41a60 100644 --- a/src/deepgram/types/speak_settings_v1.py +++ b/src/deepgram/types/speak_settings_v1.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .speak_settings_v1endpoint import SpeakSettingsV1Endpoint from .speak_settings_v1provider import SpeakSettingsV1Provider -class SpeakSettingsV1(UniversalBaseModel): +class SpeakSettingsV1(UncheckedBaseModel): provider: SpeakSettingsV1Provider endpoint: typing.Optional[SpeakSettingsV1Endpoint] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/speak_settings_v1endpoint.py b/src/deepgram/types/speak_settings_v1endpoint.py index 2565df72..ac806e29 100644 --- a/src/deepgram/types/speak_settings_v1endpoint.py +++ b/src/deepgram/types/speak_settings_v1endpoint.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class SpeakSettingsV1Endpoint(UniversalBaseModel): +class SpeakSettingsV1Endpoint(UncheckedBaseModel): """ Optional if provider is Deepgram. Required for non-Deepgram TTS providers. When present, must include url field and headers object. Valid schemes are https and wss with wss only supported for Eleven Labs. diff --git a/src/deepgram/types/speak_settings_v1provider.py b/src/deepgram/types/speak_settings_v1provider.py index 7a1e1cb7..5fe6606d 100644 --- a/src/deepgram/types/speak_settings_v1provider.py +++ b/src/deepgram/types/speak_settings_v1provider.py @@ -6,7 +6,8 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel, UnionMetadata from .aws_polly_speak_provider_credentials import AwsPollySpeakProviderCredentials from .aws_polly_speak_provider_engine import AwsPollySpeakProviderEngine from .aws_polly_speak_provider_voice import AwsPollySpeakProviderVoice @@ -18,7 +19,7 @@ from .open_ai_speak_provider_voice import OpenAiSpeakProviderVoice -class SpeakSettingsV1Provider_Deepgram(UniversalBaseModel): +class SpeakSettingsV1Provider_Deepgram(UncheckedBaseModel): type: typing.Literal["deepgram"] = "deepgram" version: typing.Optional[typing.Literal["v1"]] = None model: DeepgramSpeakProviderModel @@ -33,7 +34,7 @@ class Config: extra = pydantic.Extra.allow -class SpeakSettingsV1Provider_ElevenLabs(UniversalBaseModel): +class SpeakSettingsV1Provider_ElevenLabs(UncheckedBaseModel): type: typing.Literal["eleven_labs"] = "eleven_labs" version: typing.Optional[typing.Literal["v1"]] = None model_id: ElevenLabsSpeakProviderModelId @@ -50,7 +51,7 @@ class Config: extra = pydantic.Extra.allow -class SpeakSettingsV1Provider_Cartesia(UniversalBaseModel): +class SpeakSettingsV1Provider_Cartesia(UncheckedBaseModel): type: typing.Literal["cartesia"] = "cartesia" version: typing.Optional[typing.Literal["2025-03-17"]] = None model_id: CartesiaSpeakProviderModelId @@ -67,7 +68,7 @@ class Config: extra = pydantic.Extra.allow -class SpeakSettingsV1Provider_OpenAi(UniversalBaseModel): +class SpeakSettingsV1Provider_OpenAi(UncheckedBaseModel): type: typing.Literal["open_ai"] = "open_ai" version: typing.Optional[typing.Literal["v1"]] = None model: OpenAiSpeakProviderModel @@ -83,7 +84,7 @@ class Config: extra = pydantic.Extra.allow -class SpeakSettingsV1Provider_AwsPolly(UniversalBaseModel): +class SpeakSettingsV1Provider_AwsPolly(UncheckedBaseModel): type: typing.Literal["aws_polly"] = "aws_polly" voice: AwsPollySpeakProviderVoice language: str @@ -109,5 +110,5 @@ class Config: SpeakSettingsV1Provider_OpenAi, SpeakSettingsV1Provider_AwsPolly, ], - pydantic.Field(discriminator="type"), + UnionMetadata(discriminant="type"), ] diff --git a/src/deepgram/types/think_settings_v1.py b/src/deepgram/types/think_settings_v1.py index 347030f0..f74c63d1 100644 --- a/src/deepgram/types/think_settings_v1.py +++ b/src/deepgram/types/think_settings_v1.py @@ -3,14 +3,15 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .think_settings_v1context_length import ThinkSettingsV1ContextLength from .think_settings_v1endpoint import ThinkSettingsV1Endpoint from .think_settings_v1functions_item import ThinkSettingsV1FunctionsItem from .think_settings_v1provider import ThinkSettingsV1Provider -class ThinkSettingsV1(UniversalBaseModel): +class ThinkSettingsV1(UncheckedBaseModel): provider: ThinkSettingsV1Provider endpoint: typing.Optional[ThinkSettingsV1Endpoint] = pydantic.Field(default=None) """ diff --git a/src/deepgram/types/think_settings_v1endpoint.py b/src/deepgram/types/think_settings_v1endpoint.py index 4391953f..a98942ca 100644 --- a/src/deepgram/types/think_settings_v1endpoint.py +++ b/src/deepgram/types/think_settings_v1endpoint.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ThinkSettingsV1Endpoint(UniversalBaseModel): +class ThinkSettingsV1Endpoint(UncheckedBaseModel): """ Optional for non-Deepgram LLM providers. When present, must include url field and headers object """ diff --git a/src/deepgram/types/think_settings_v1functions_item.py b/src/deepgram/types/think_settings_v1functions_item.py index 92bacdae..6a142ae5 100644 --- a/src/deepgram/types/think_settings_v1functions_item.py +++ b/src/deepgram/types/think_settings_v1functions_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .think_settings_v1functions_item_endpoint import ThinkSettingsV1FunctionsItemEndpoint -class ThinkSettingsV1FunctionsItem(UniversalBaseModel): +class ThinkSettingsV1FunctionsItem(UncheckedBaseModel): name: typing.Optional[str] = pydantic.Field(default=None) """ Function name diff --git a/src/deepgram/types/think_settings_v1functions_item_endpoint.py b/src/deepgram/types/think_settings_v1functions_item_endpoint.py index 44867f5d..b3e0148e 100644 --- a/src/deepgram/types/think_settings_v1functions_item_endpoint.py +++ b/src/deepgram/types/think_settings_v1functions_item_endpoint.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class ThinkSettingsV1FunctionsItemEndpoint(UniversalBaseModel): +class ThinkSettingsV1FunctionsItemEndpoint(UncheckedBaseModel): """ The Function endpoint to call. if not passed, function is called client-side """ diff --git a/src/deepgram/types/think_settings_v1provider.py b/src/deepgram/types/think_settings_v1provider.py index 85b32ff6..799ec07d 100644 --- a/src/deepgram/types/think_settings_v1provider.py +++ b/src/deepgram/types/think_settings_v1provider.py @@ -6,7 +6,8 @@ import pydantic import typing_extensions -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel, UnionMetadata from .anthropic_think_provider_model import AnthropicThinkProviderModel from .aws_bedrock_think_provider_credentials import AwsBedrockThinkProviderCredentials from .aws_bedrock_think_provider_model import AwsBedrockThinkProviderModel @@ -14,7 +15,7 @@ from .open_ai_think_provider_model import OpenAiThinkProviderModel -class ThinkSettingsV1Provider_OpenAi(UniversalBaseModel): +class ThinkSettingsV1Provider_OpenAi(UncheckedBaseModel): type: typing.Literal["open_ai"] = "open_ai" version: typing.Optional[typing.Literal["v1"]] = None model: OpenAiThinkProviderModel @@ -30,7 +31,7 @@ class Config: extra = pydantic.Extra.allow -class ThinkSettingsV1Provider_AwsBedrock(UniversalBaseModel): +class ThinkSettingsV1Provider_AwsBedrock(UncheckedBaseModel): type: typing.Literal["aws_bedrock"] = "aws_bedrock" model: AwsBedrockThinkProviderModel temperature: typing.Optional[float] = None @@ -46,7 +47,7 @@ class Config: extra = pydantic.Extra.allow -class ThinkSettingsV1Provider_Anthropic(UniversalBaseModel): +class ThinkSettingsV1Provider_Anthropic(UncheckedBaseModel): type: typing.Literal["anthropic"] = "anthropic" version: typing.Optional[typing.Literal["v1"]] = None model: AnthropicThinkProviderModel @@ -62,7 +63,7 @@ class Config: extra = pydantic.Extra.allow -class ThinkSettingsV1Provider_Google(UniversalBaseModel): +class ThinkSettingsV1Provider_Google(UncheckedBaseModel): type: typing.Literal["google"] = "google" version: typing.Optional[typing.Literal["v1beta"]] = None model: GoogleThinkProviderModel @@ -78,7 +79,7 @@ class Config: extra = pydantic.Extra.allow -class ThinkSettingsV1Provider_Groq(UniversalBaseModel): +class ThinkSettingsV1Provider_Groq(UncheckedBaseModel): type: typing.Literal["groq"] = "groq" version: typing.Optional[typing.Literal["v1"]] = None model: typing.Literal["openai/gpt-oss-20b"] = "openai/gpt-oss-20b" @@ -102,5 +103,5 @@ class Config: ThinkSettingsV1Provider_Google, ThinkSettingsV1Provider_Groq, ], - pydantic.Field(discriminator="type"), + UnionMetadata(discriminant="type"), ] diff --git a/src/deepgram/types/update_project_member_scopes_v1response.py b/src/deepgram/types/update_project_member_scopes_v1response.py index 1b284f1c..ae6e9997 100644 --- a/src/deepgram/types/update_project_member_scopes_v1response.py +++ b/src/deepgram/types/update_project_member_scopes_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UpdateProjectMemberScopesV1Response(UniversalBaseModel): +class UpdateProjectMemberScopesV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/update_project_v1response.py b/src/deepgram/types/update_project_v1response.py index beac96e0..73900c5e 100644 --- a/src/deepgram/types/update_project_v1response.py +++ b/src/deepgram/types/update_project_v1response.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UpdateProjectV1Response(UniversalBaseModel): +class UpdateProjectV1Response(UncheckedBaseModel): message: typing.Optional[str] = pydantic.Field(default=None) """ confirmation message diff --git a/src/deepgram/types/usage_breakdown_v1response.py b/src/deepgram/types/usage_breakdown_v1response.py index b701f98c..8ec19bb6 100644 --- a/src/deepgram/types/usage_breakdown_v1response.py +++ b/src/deepgram/types/usage_breakdown_v1response.py @@ -3,12 +3,13 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .usage_breakdown_v1response_resolution import UsageBreakdownV1ResponseResolution from .usage_breakdown_v1response_results_item import UsageBreakdownV1ResponseResultsItem -class UsageBreakdownV1Response(UniversalBaseModel): +class UsageBreakdownV1Response(UncheckedBaseModel): start: str = pydantic.Field() """ Start date of the usage period diff --git a/src/deepgram/types/usage_breakdown_v1response_resolution.py b/src/deepgram/types/usage_breakdown_v1response_resolution.py index 2d05428c..a4eddbe6 100644 --- a/src/deepgram/types/usage_breakdown_v1response_resolution.py +++ b/src/deepgram/types/usage_breakdown_v1response_resolution.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UsageBreakdownV1ResponseResolution(UniversalBaseModel): +class UsageBreakdownV1ResponseResolution(UncheckedBaseModel): units: str = pydantic.Field() """ Time unit for the resolution diff --git a/src/deepgram/types/usage_breakdown_v1response_results_item.py b/src/deepgram/types/usage_breakdown_v1response_results_item.py index 1675a1b1..75f2a7cc 100644 --- a/src/deepgram/types/usage_breakdown_v1response_results_item.py +++ b/src/deepgram/types/usage_breakdown_v1response_results_item.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .usage_breakdown_v1response_results_item_grouping import UsageBreakdownV1ResponseResultsItemGrouping -class UsageBreakdownV1ResponseResultsItem(UniversalBaseModel): +class UsageBreakdownV1ResponseResultsItem(UncheckedBaseModel): hours: float = pydantic.Field() """ Audio hours processed diff --git a/src/deepgram/types/usage_breakdown_v1response_results_item_grouping.py b/src/deepgram/types/usage_breakdown_v1response_results_item_grouping.py index 6c41d64b..c1966d9f 100644 --- a/src/deepgram/types/usage_breakdown_v1response_results_item_grouping.py +++ b/src/deepgram/types/usage_breakdown_v1response_results_item_grouping.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UsageBreakdownV1ResponseResultsItemGrouping(UniversalBaseModel): +class UsageBreakdownV1ResponseResultsItemGrouping(UncheckedBaseModel): start: typing.Optional[str] = pydantic.Field(default=None) """ Start date for this group diff --git a/src/deepgram/types/usage_fields_v1response.py b/src/deepgram/types/usage_fields_v1response.py index 3e4551db..91b26835 100644 --- a/src/deepgram/types/usage_fields_v1response.py +++ b/src/deepgram/types/usage_fields_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .usage_fields_v1response_models_item import UsageFieldsV1ResponseModelsItem -class UsageFieldsV1Response(UniversalBaseModel): +class UsageFieldsV1Response(UncheckedBaseModel): tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ List of tags associated with the project diff --git a/src/deepgram/types/usage_fields_v1response_models_item.py b/src/deepgram/types/usage_fields_v1response_models_item.py index 36fa7baa..95418ac4 100644 --- a/src/deepgram/types/usage_fields_v1response_models_item.py +++ b/src/deepgram/types/usage_fields_v1response_models_item.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UsageFieldsV1ResponseModelsItem(UniversalBaseModel): +class UsageFieldsV1ResponseModelsItem(UncheckedBaseModel): name: typing.Optional[str] = pydantic.Field(default=None) """ Name of the model. diff --git a/src/deepgram/types/usage_v1response.py b/src/deepgram/types/usage_v1response.py index d338d249..0d7133e8 100644 --- a/src/deepgram/types/usage_v1response.py +++ b/src/deepgram/types/usage_v1response.py @@ -3,11 +3,12 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel from .usage_v1response_resolution import UsageV1ResponseResolution -class UsageV1Response(UniversalBaseModel): +class UsageV1Response(UncheckedBaseModel): start: typing.Optional[str] = None end: typing.Optional[str] = None resolution: typing.Optional[UsageV1ResponseResolution] = None diff --git a/src/deepgram/types/usage_v1response_resolution.py b/src/deepgram/types/usage_v1response_resolution.py index e6d9289c..8e4123a7 100644 --- a/src/deepgram/types/usage_v1response_resolution.py +++ b/src/deepgram/types/usage_v1response_resolution.py @@ -3,10 +3,11 @@ import typing import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel -class UsageV1ResponseResolution(UniversalBaseModel): +class UsageV1ResponseResolution(UncheckedBaseModel): units: typing.Optional[str] = None amount: typing.Optional[float] = None diff --git a/tests/custom/test_text_builder.py b/tests/custom/test_text_builder.py deleted file mode 100644 index 77a7ed1b..00000000 --- a/tests/custom/test_text_builder.py +++ /dev/null @@ -1,500 +0,0 @@ -""" -Tests for TextBuilder and TTS helper utilities -""" - -import pytest -from deepgram.helpers import ( - TextBuilder, - add_pronunciation, - ssml_to_deepgram, - validate_ipa, - validate_pause, -) - - -class TestTextBuilder: - """Tests for the TextBuilder class""" - - def test_basic_text(self): - """Test adding plain text""" - builder = TextBuilder() - result = builder.text("Hello world").build() - assert result == "Hello world" - - def test_multiple_text_parts(self): - """Test chaining multiple text parts""" - builder = TextBuilder() - result = builder.text("Hello ").text("world").build() - assert result == "Hello world" - - def test_pronunciation(self): - """Test adding pronunciation""" - builder = TextBuilder() - result = builder.pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn").build() - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - - def test_text_with_pronunciation(self): - """Test mixing text and pronunciation""" - builder = TextBuilder() - result = ( - builder - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily") - .build() - ) - assert "Take " in result - assert '"word": "azathioprine"' in result - assert " twice daily" in result - - def test_pause(self): - """Test adding pause""" - builder = TextBuilder() - result = builder.pause(500).build() - assert result == "{pause:500}" - - def test_text_with_pause(self): - """Test mixing text and pause""" - builder = TextBuilder() - result = ( - builder - .text("Hello") - .pause(1000) - .text("world") - .build() - ) - assert result == "Hello{pause:1000}world" - - def test_complex_chain(self): - """Test complex chaining with all features""" - builder = TextBuilder() - result = ( - builder - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily with ") - .pronunciation("dupilumab", "duːˈpɪljuːmæb") - .text(" injections") - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - assert "Take " in result - assert '"word": "azathioprine"' in result - assert " twice daily with " in result - assert '"word": "dupilumab"' in result - assert " injections" in result - assert "{pause:500}" in result - assert " Do not exceed prescribed dosage." in result - - def test_pronunciation_limit(self): - """Test pronunciation count limit (500 max)""" - builder = TextBuilder() - - # Add 500 pronunciations (should work) - for i in range(500): - builder.pronunciation(f"word{i}", "test") - - # 501st should raise error - with pytest.raises(ValueError, match="Maximum 500 pronunciations"): - builder.pronunciation("extra", "test") - - def test_pause_limit(self): - """Test pause count limit (50 max)""" - builder = TextBuilder() - - # Add 50 pauses (should work) - for i in range(50): - builder.pause(500) - - # 51st should raise error - with pytest.raises(ValueError, match="Maximum 50 pauses"): - builder.pause(500) - - def test_character_limit(self): - """Test character count validation (2000 max)""" - builder = TextBuilder() - - # Add text approaching the limit - builder.text("x" * 2000) - - # Should work at exactly 2000 - result = builder.build() - assert len(result) == 2000 - - # Exceeding should raise error - builder2 = TextBuilder() - builder2.text("x" * 2001) - with pytest.raises(ValueError, match="exceeds 2000 character limit"): - builder2.build() - - def test_empty_builder(self): - """Test building with no content""" - builder = TextBuilder() - result = builder.build() - assert result == "" - - def test_invalid_ipa(self): - """Test validation of IPA pronunciation""" - builder = TextBuilder() - - # Should reject IPA with invalid characters - with pytest.raises(ValueError, match="invalid character"): - builder.pronunciation("word", 'invalid"quote') - - with pytest.raises(ValueError, match="invalid character"): - builder.pronunciation("word", "invalid\nline") - - def test_invalid_pause_duration(self): - """Test pause duration validation""" - builder = TextBuilder() - - # Too short - with pytest.raises(ValueError, match="at least 500ms"): - builder.pause(400) - - # Too long - with pytest.raises(ValueError, match="not exceed 5000ms"): - builder.pause(5001) - - # Not in 100ms increments - with pytest.raises(ValueError, match="100ms increments"): - builder.pause(550) - - def test_pause_boundary_values(self): - """Test pause at valid boundaries""" - builder = TextBuilder() - - # Minimum valid - result1 = builder.pause(500).build() - assert "{pause:500}" in result1 - - # Maximum valid - builder2 = TextBuilder() - result2 = builder2.pause(5000).build() - assert "{pause:5000}" in result2 - - -class TestAddPronunciation: - """Tests for the add_pronunciation function""" - - def test_basic_replacement(self): - """Test basic word replacement""" - text = "Take azathioprine twice daily." - result = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - assert "Take " in result - assert " twice daily." in result - - def test_multiple_replacements(self): - """Test replacing multiple words""" - text = "Take azathioprine twice daily with dupilumab injections." - text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") - - assert '"word": "azathioprine"' in text - assert '"word": "dupilumab"' in text - - def test_whole_word_only(self): - """Test that replacement only affects whole words""" - text = "The therapist prescribed therapy." - result = add_pronunciation(text, "The", "ðiː") - - # Should only replace "The", not "the" in "therapist" or "therapy" - assert result.count('"word"') == 1 - assert "therapist" in result - assert "therapy" in result - - def test_case_sensitive(self): - """Test that replacement is case-sensitive""" - text = "Take azathioprine. AZATHIOPRINE is different." - result = add_pronunciation(text, "azathioprine", "test") - - # Should only replace lowercase version (first occurrence) - assert result.count('"word"') == 1 - assert "AZATHIOPRINE" in result - - def test_word_not_found(self): - """Test replacement when word is not in text""" - text = "Hello world" - result = add_pronunciation(text, "missing", "test") - - # Text should be unchanged - assert result == text - - -class TestSsmlToDeepgram: - """Tests for SSML conversion""" - - def test_basic_phoneme(self): - """Test converting basic phoneme tag""" - ssml = 'azathioprine' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - - def test_basic_break(self): - """Test converting break tag (milliseconds)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - assert result == "{pause:500}" - - def test_break_seconds(self): - """Test converting break tag (seconds)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - assert result == "{pause:500}" - - def test_speak_wrapper(self): - """Test handling wrapper tag""" - ssml = 'Hello world' - result = ssml_to_deepgram(ssml) - - assert result == "Hello world" - - def test_complex_ssml(self): - """Test complex SSML with multiple elements""" - ssml = ''' - Take azathioprine - Do not exceed dosage. - ''' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert "{pause:500}" in result - assert "Do not exceed dosage." in result - - def test_multiple_phonemes(self): - """Test multiple phoneme tags""" - ssml = '''Take azathioprine - with dupilumab''' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert '"word": "dupilumab"' in result - - def test_plain_text(self): - """Test plain text without SSML tags""" - text = "Hello world" - result = ssml_to_deepgram(text) - - assert result == text - - def test_break_out_of_range(self): - """Test break with out-of-range duration (should round to valid)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - # Should round to nearest valid value (500ms) - assert "{pause:" in result - - -class TestFromSsml: - """Tests for TextBuilder.from_ssml() method""" - - def test_from_ssml_basic(self): - """Test parsing SSML into builder""" - ssml = 'Hello world' - builder = TextBuilder() - result = builder.from_ssml(ssml).build() - - assert "Hello world" in result - - def test_from_ssml_with_additional_text(self): - """Test mixing SSML parsing with additional builder methods""" - ssml = 'Take medicine' - builder = TextBuilder() - result = ( - builder - .from_ssml(ssml) - .pause(500) - .text(" Do not exceed dosage.") - .build() - ) - - assert '"word": "medicine"' in result - assert "{pause:500}" in result - assert "Do not exceed dosage." in result - - def test_from_ssml_counts_pronunciations(self): - """Test that from_ssml updates internal counters""" - # Create SSML with pronunciations - pronunciations = ''.join([ - f'word{i} ' - for i in range(500) - ]) - ssml = f'{pronunciations}' - - builder = TextBuilder() - builder.from_ssml(ssml) - - # Should hit the limit - with pytest.raises(ValueError, match="Maximum 500 pronunciations"): - builder.pronunciation("extra", "test") - - -class TestValidateIpa: - """Tests for IPA validation""" - - def test_valid_ipa(self): - """Test valid IPA strings""" - is_valid, msg = validate_ipa("ˌæzəˈθaɪəpriːn") - assert is_valid is True - assert msg == "" - - def test_empty_ipa(self): - """Test empty IPA string""" - is_valid, msg = validate_ipa("") - assert is_valid is False - assert "cannot be empty" in msg - - def test_invalid_characters(self): - """Test IPA with invalid characters""" - # Double quote - is_valid, msg = validate_ipa('test"quote') - assert is_valid is False - assert "invalid character" in msg - - # Newline - is_valid, msg = validate_ipa("test\nline") - assert is_valid is False - assert "invalid character" in msg - - def test_too_long(self): - """Test IPA exceeding length limit""" - is_valid, msg = validate_ipa("x" * 101) - assert is_valid is False - assert "exceeds 100 character limit" in msg - - def test_not_string(self): - """Test non-string IPA""" - is_valid, msg = validate_ipa(123) - assert is_valid is False - assert "must be a string" in msg - - -class TestValidatePause: - """Tests for pause validation""" - - def test_valid_pauses(self): - """Test valid pause durations""" - # Minimum - is_valid, msg = validate_pause(500) - assert is_valid is True - - # Maximum - is_valid, msg = validate_pause(5000) - assert is_valid is True - - # Mid-range - is_valid, msg = validate_pause(2500) - assert is_valid is True - - def test_too_short(self): - """Test pause below minimum""" - is_valid, msg = validate_pause(400) - assert is_valid is False - assert "at least 500ms" in msg - - def test_too_long(self): - """Test pause above maximum""" - is_valid, msg = validate_pause(5001) - assert is_valid is False - assert "not exceed 5000ms" in msg - - def test_invalid_increment(self): - """Test pause not in 100ms increments""" - is_valid, msg = validate_pause(550) - assert is_valid is False - assert "100ms increments" in msg - - def test_not_integer(self): - """Test non-integer pause""" - is_valid, msg = validate_pause(500.5) - assert is_valid is False - assert "must be an integer" in msg - - -class TestIntegration: - """Integration tests combining multiple features""" - - def test_medical_example(self): - """Test the medical prescription example from the spec""" - text = ( - TextBuilder() - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily with ") - .pronunciation("dupilumab", "duːˈpɪljuːmæb") - .text(" injections") - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - # Verify all components are present - assert "Take " in text - assert '"word": "azathioprine"' in text - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text - assert " twice daily with " in text - assert '"word": "dupilumab"' in text - assert '"pronounce": "duːˈpɪljuːmæb"' in text - assert " injections" in text - assert "{pause:500}" in text - assert " Do not exceed prescribed dosage." in text - - def test_ssml_migration(self): - """Test SSML to Deepgram migration workflow""" - ssml = ''' - Take azathioprine - Do not exceed dosage. - ''' - - # Method 1: Direct conversion - text1 = ssml_to_deepgram(ssml) - - # Method 2: Using builder - text2 = TextBuilder().from_ssml(ssml).build() - - # Both should produce similar results - assert '"word": "azathioprine"' in text1 - assert "{pause:500}" in text1 - assert '"word": "azathioprine"' in text2 - assert "{pause:500}" in text2 - - def test_builder_with_ssml_and_additions(self): - """Test the mixed usage example from the spec""" - some_imported_ssml = ''' - Take medicine - ''' - - text = ( - TextBuilder() - .from_ssml(some_imported_ssml) - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - assert '"word": "medicine"' in text - assert "{pause:500}" in text - assert " Do not exceed prescribed dosage." in text - - def test_standalone_function_workflow(self): - """Test using standalone add_pronunciation function""" - text = "Take azathioprine twice daily with dupilumab injections." - text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") - - assert '"word": "azathioprine"' in text - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text - assert '"word": "dupilumab"' in text - assert '"pronounce": "duːˈpɪljuːmæb"' in text - diff --git a/tests/custom/test_transport.py b/tests/custom/test_transport.py deleted file mode 100644 index ba860fa5..00000000 --- a/tests/custom/test_transport.py +++ /dev/null @@ -1,481 +0,0 @@ -"""Tests for custom WebSocket transport support.""" - -import json -import sys -from typing import Any, Dict, Iterator, List -from unittest.mock import MagicMock - -import pytest - -from deepgram.transport import ( - AsyncTransport, - SyncTransport, - _AsyncTransportShim, - _SyncTransportShim, - _TARGET_MODULES, - install_transport, - restore_transport, -) - - -# --------------------------------------------------------------------------- -# Mock transport implementations -# --------------------------------------------------------------------------- - -class MockSyncTransport: - """Minimal sync transport that satisfies the SyncTransport protocol.""" - - def __init__(self, messages: List[str] = None): - self._messages = list(messages or []) - self._sent: List[Any] = [] - self._closed = False - - def send(self, data: Any) -> None: - self._sent.append(data) - - def recv(self) -> str: - if self._messages: - return self._messages.pop(0) - raise StopIteration - - def __iter__(self) -> Iterator: - return iter(self._messages) - - def close(self) -> None: - self._closed = True - - -class MockAsyncTransport: - """Minimal async transport that satisfies the AsyncTransport protocol.""" - - def __init__(self, messages: List[str] = None): - self._messages = list(messages or []) - self._sent: List[Any] = [] - self._closed = False - - async def send(self, data: Any) -> None: - self._sent.append(data) - - async def recv(self) -> str: - if self._messages: - return self._messages.pop(0) - raise StopAsyncIteration - - async def __aiter__(self): - for msg in self._messages: - yield msg - - async def close(self) -> None: - self._closed = True - - -# --------------------------------------------------------------------------- -# Fixtures -# --------------------------------------------------------------------------- - -@pytest.fixture(autouse=True) -def _restore_after_test(): - """Ensure transport patches are cleaned up after every test.""" - yield - restore_transport() - - -# --------------------------------------------------------------------------- -# Protocol conformance -# --------------------------------------------------------------------------- - -class TestProtocolConformance: - def test_sync_transport_protocol(self): - transport = MockSyncTransport() - assert isinstance(transport, SyncTransport) - - def test_async_transport_protocol(self): - transport = MockAsyncTransport() - assert isinstance(transport, AsyncTransport) - - def test_object_not_conforming_sync(self): - assert not isinstance(object(), SyncTransport) - - def test_object_not_conforming_async(self): - assert not isinstance(object(), AsyncTransport) - - -# --------------------------------------------------------------------------- -# Sync shim -# --------------------------------------------------------------------------- - -class TestSyncTransportShim: - def test_connect_calls_factory(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com", additional_headers={"Authorization": "token xyz"}) as t: - assert t is transport - - factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) - - def test_connect_closes_transport(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com"): - assert not transport._closed - - assert transport._closed - - def test_connect_default_headers(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com"): - pass - - factory.assert_called_once_with("wss://example.com", {}) - - -# --------------------------------------------------------------------------- -# Async shim -# --------------------------------------------------------------------------- - -class TestAsyncTransportShim: - async def test_connect_calls_factory(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com", extra_headers={"Authorization": "token xyz"}) as t: - assert t is transport - - factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) - - async def test_connect_closes_transport(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com"): - assert not transport._closed - - assert transport._closed - - async def test_connect_default_headers(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com"): - pass - - factory.assert_called_once_with("wss://example.com", {}) - - -# --------------------------------------------------------------------------- -# install_transport / restore_transport -# --------------------------------------------------------------------------- - -def _ensure_modules_loaded(): - """Force-import all target modules so they appear in sys.modules.""" - for mod_path in _TARGET_MODULES: - if mod_path not in sys.modules: - __import__(mod_path) - - -class TestInstallRestore: - def test_install_sync_patches_all_modules(self): - _ensure_modules_loaded() - - factory = MagicMock() - install_transport(sync_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert isinstance(mod.websockets_sync_client, _SyncTransportShim), ( - f"{mod_path}.websockets_sync_client was not patched" - ) - - def test_install_async_patches_all_modules(self): - _ensure_modules_loaded() - - factory = MagicMock() - install_transport(async_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_client_connect"): - assert isinstance(mod.websockets_client_connect, _AsyncTransportShim), ( - f"{mod_path}.websockets_client_connect was not patched" - ) - - def test_restore_undoes_patches(self): - _ensure_modules_loaded() - - # Capture originals - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = { - "sync": getattr(mod, "websockets_sync_client", None), - "async": getattr(mod, "websockets_client_connect", None), - } - - install_transport(sync_factory=MagicMock(), async_factory=MagicMock()) - restore_transport() - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path]["sync"] is not None: - assert mod.websockets_sync_client is originals[mod_path]["sync"], ( - f"{mod_path}.websockets_sync_client was not restored" - ) - if originals[mod_path]["async"] is not None: - assert mod.websockets_client_connect is originals[mod_path]["async"], ( - f"{mod_path}.websockets_client_connect was not restored" - ) - - def test_install_only_sync_leaves_async_untouched(self): - _ensure_modules_loaded() - - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = getattr(mod, "websockets_client_connect", None) - - install_transport(sync_factory=MagicMock()) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path] is not None: - assert mod.websockets_client_connect is originals[mod_path] - - def test_install_only_async_leaves_sync_untouched(self): - _ensure_modules_loaded() - - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = getattr(mod, "websockets_sync_client", None) - - install_transport(async_factory=MagicMock()) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path] is not None: - assert mod.websockets_sync_client is originals[mod_path] - - -# --------------------------------------------------------------------------- -# Conflict guard -# --------------------------------------------------------------------------- - -class TestConflictGuard: - def test_same_sync_factory_is_idempotent(self): - _ensure_modules_loaded() - factory = MagicMock() - install_transport(sync_factory=factory) - install_transport(sync_factory=factory) # should not raise - - def test_same_async_factory_is_idempotent(self): - _ensure_modules_loaded() - factory = MagicMock() - install_transport(async_factory=factory) - install_transport(async_factory=factory) # should not raise - - def test_different_sync_factory_raises(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - with pytest.raises(RuntimeError, match="different sync transport factory"): - install_transport(sync_factory=MagicMock()) - - def test_different_async_factory_raises(self): - _ensure_modules_loaded() - install_transport(async_factory=MagicMock()) - with pytest.raises(RuntimeError, match="different async transport factory"): - install_transport(async_factory=MagicMock()) - - def test_restore_then_reinstall_different_factory(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - restore_transport() - install_transport(sync_factory=MagicMock()) # should not raise - - def test_sync_and_async_factories_are_independent(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - install_transport(async_factory=MagicMock()) # should not raise - - -# --------------------------------------------------------------------------- -# End-to-end: sync listen with mock transport -# --------------------------------------------------------------------------- - -def _valid_metadata_json() -> str: - """Return a JSON string that matches the ListenV1Metadata Pydantic model.""" - return json.dumps({ - "type": "Metadata", - "transaction_key": "test-txn-key", - "request_id": "req-001", - "sha256": "abc123", - "created": "2024-01-01T00:00:00Z", - "duration": 1.5, - "channels": 1, - }) - - -class TestSyncEndToEnd: - def test_listen_v1_with_mock_transport(self): - """Verify a mock transport receives messages through the event system.""" - from deepgram.core.events import EventEmitterMixin, EventType - from deepgram.listen.v1.socket_client import V1SocketClient - - transcript_json = _valid_metadata_json() - - transport = MockSyncTransport(messages=[transcript_json]) - client = V1SocketClient(websocket=transport) - - received = [] - errors = [] - client.on(EventType.MESSAGE, lambda msg: received.append(msg)) - client.on(EventType.ERROR, lambda err: errors.append(err)) - - client.start_listening() - - assert len(errors) == 0 - assert len(received) == 1 - - def test_custom_transport_error_emits_error_event(self): - """When the transport raises, EventType.ERROR should fire.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import V1SocketClient - - class FailingTransport: - def send(self, data): pass - def recv(self): raise ConnectionError("boom") - def close(self): pass - def __iter__(self): - raise ConnectionError("boom") - - client = V1SocketClient(websocket=FailingTransport()) - - errors = [] - closed = [] - client.on(EventType.ERROR, lambda err: errors.append(err)) - client.on(EventType.CLOSE, lambda _: closed.append(True)) - - client.start_listening() - - assert len(errors) == 1 - assert isinstance(errors[0], ConnectionError) - assert len(closed) == 1 - - -# --------------------------------------------------------------------------- -# End-to-end: async listen with mock transport -# --------------------------------------------------------------------------- - -class TestAsyncEndToEnd: - async def test_listen_v1_async_with_mock_transport(self): - """Verify a mock async transport works through the event system.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import AsyncV1SocketClient - - transcript_json = _valid_metadata_json() - - class AsyncMockWS: - def __init__(self): - self._messages = [transcript_json] - - async def send(self, data): pass - async def recv(self): return self._messages.pop(0) - async def close(self): pass - - async def __aiter__(self): - for msg in list(self._messages): - yield msg - - transport = AsyncMockWS() - client = AsyncV1SocketClient(websocket=transport) - - received = [] - errors = [] - client.on(EventType.MESSAGE, lambda msg: received.append(msg)) - client.on(EventType.ERROR, lambda err: errors.append(err)) - - await client.start_listening() - - assert len(errors) == 0 - assert len(received) == 1 - - async def test_async_transport_error_emits_error_event(self): - """When the async transport raises, EventType.ERROR should fire.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import AsyncV1SocketClient - - class FailingAsyncTransport: - async def send(self, data): pass - async def recv(self): raise ConnectionError("async boom") - async def close(self): pass - - async def __aiter__(self): - raise ConnectionError("async boom") - yield # unreachable — makes this an async generator - - client = AsyncV1SocketClient(websocket=FailingAsyncTransport()) - - errors = [] - closed = [] - client.on(EventType.ERROR, lambda err: errors.append(err)) - client.on(EventType.CLOSE, lambda _: closed.append(True)) - - await client.start_listening() - - assert len(errors) == 1 - assert isinstance(errors[0], ConnectionError) - assert len(closed) == 1 - - -# --------------------------------------------------------------------------- -# DeepgramClient construction triggers patching -# --------------------------------------------------------------------------- - -class TestClientConstruction: - def test_deepgram_client_installs_sync_transport(self): - _ensure_modules_loaded() - - factory = MagicMock() - from deepgram.client import DeepgramClient - DeepgramClient(api_key="test-key", transport_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert isinstance(mod.websockets_sync_client, _SyncTransportShim) - - def test_deepgram_client_without_factory_does_not_patch(self): - _ensure_modules_loaded() - - # Ensure clean state - restore_transport() - - from deepgram.client import DeepgramClient - DeepgramClient(api_key="test-key") - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert not isinstance(mod.websockets_sync_client, _SyncTransportShim) - - def test_async_deepgram_client_installs_async_transport(self): - _ensure_modules_loaded() - - factory = MagicMock() - from deepgram.client import AsyncDeepgramClient - AsyncDeepgramClient(api_key="test-key", transport_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_client_connect"): - assert isinstance(mod.websockets_client_connect, _AsyncTransportShim) From 89824c5eda8e1f7d5d9ca222a060f19ba7dea164 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 12:35:56 +0000 Subject: [PATCH 02/11] fix: set version to 6.0.1, restore deleted tests, unlock socket_client regen - Set SDK version to 6.0.1 in pyproject.toml and client_wrapper.py - Restore test_text_builder.py and test_transport.py deleted by Fern regen - Comment out socket_client.py paths in .fernignore so Fern can regenerate them --- .fernignore | 8 +- pyproject.toml | 2 +- src/deepgram/core/client_wrapper.py | 2 +- tests/custom/test_text_builder.py | 500 ++++++++++++++++++++++++++++ tests/custom/test_transport.py | 481 ++++++++++++++++++++++++++ 5 files changed, 987 insertions(+), 6 deletions(-) create mode 100644 tests/custom/test_text_builder.py create mode 100644 tests/custom/test_transport.py diff --git a/.fernignore b/.fernignore index d8dd04aa..796e20de 100644 --- a/.fernignore +++ b/.fernignore @@ -15,10 +15,10 @@ tests/wire/test_listen_v1_media.py # - Optional message parameter defaults for send_flush, send_close, send_clear, # send_finalize, send_close_stream, send_keep_alive # - Removed unused imports (JSONDecodeError, websockets) flagged by ruff F401 -src/deepgram/speak/v1/socket_client.py -src/deepgram/listen/v1/socket_client.py -src/deepgram/listen/v2/socket_client.py -src/deepgram/agent/v1/socket_client.py +# src/deepgram/speak/v1/socket_client.py +# src/deepgram/listen/v1/socket_client.py +# src/deepgram/listen/v2/socket_client.py +# src/deepgram/agent/v1/socket_client.py # Manual standalone tests tests/manual diff --git a/pyproject.toml b/pyproject.toml index 3a0beb7f..a11551e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "deepgram-sdk" -version = "0.0.333" +version = "6.0.1" description = "" readme = "README.md" authors = [] diff --git a/src/deepgram/core/client_wrapper.py b/src/deepgram/core/client_wrapper.py index e6d5f3a7..18b04517 100644 --- a/src/deepgram/core/client_wrapper.py +++ b/src/deepgram/core/client_wrapper.py @@ -29,7 +29,7 @@ def get_headers(self) -> typing.Dict[str, str]: "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "deepgram-sdk", - "X-Fern-SDK-Version": "0.0.333", + "X-Fern-SDK-Version": "6.0.1", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Token {self.api_key}" diff --git a/tests/custom/test_text_builder.py b/tests/custom/test_text_builder.py new file mode 100644 index 00000000..77a7ed1b --- /dev/null +++ b/tests/custom/test_text_builder.py @@ -0,0 +1,500 @@ +""" +Tests for TextBuilder and TTS helper utilities +""" + +import pytest +from deepgram.helpers import ( + TextBuilder, + add_pronunciation, + ssml_to_deepgram, + validate_ipa, + validate_pause, +) + + +class TestTextBuilder: + """Tests for the TextBuilder class""" + + def test_basic_text(self): + """Test adding plain text""" + builder = TextBuilder() + result = builder.text("Hello world").build() + assert result == "Hello world" + + def test_multiple_text_parts(self): + """Test chaining multiple text parts""" + builder = TextBuilder() + result = builder.text("Hello ").text("world").build() + assert result == "Hello world" + + def test_pronunciation(self): + """Test adding pronunciation""" + builder = TextBuilder() + result = builder.pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn").build() + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + + def test_text_with_pronunciation(self): + """Test mixing text and pronunciation""" + builder = TextBuilder() + result = ( + builder + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily") + .build() + ) + assert "Take " in result + assert '"word": "azathioprine"' in result + assert " twice daily" in result + + def test_pause(self): + """Test adding pause""" + builder = TextBuilder() + result = builder.pause(500).build() + assert result == "{pause:500}" + + def test_text_with_pause(self): + """Test mixing text and pause""" + builder = TextBuilder() + result = ( + builder + .text("Hello") + .pause(1000) + .text("world") + .build() + ) + assert result == "Hello{pause:1000}world" + + def test_complex_chain(self): + """Test complex chaining with all features""" + builder = TextBuilder() + result = ( + builder + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily with ") + .pronunciation("dupilumab", "duːˈpɪljuːmæb") + .text(" injections") + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + assert "Take " in result + assert '"word": "azathioprine"' in result + assert " twice daily with " in result + assert '"word": "dupilumab"' in result + assert " injections" in result + assert "{pause:500}" in result + assert " Do not exceed prescribed dosage." in result + + def test_pronunciation_limit(self): + """Test pronunciation count limit (500 max)""" + builder = TextBuilder() + + # Add 500 pronunciations (should work) + for i in range(500): + builder.pronunciation(f"word{i}", "test") + + # 501st should raise error + with pytest.raises(ValueError, match="Maximum 500 pronunciations"): + builder.pronunciation("extra", "test") + + def test_pause_limit(self): + """Test pause count limit (50 max)""" + builder = TextBuilder() + + # Add 50 pauses (should work) + for i in range(50): + builder.pause(500) + + # 51st should raise error + with pytest.raises(ValueError, match="Maximum 50 pauses"): + builder.pause(500) + + def test_character_limit(self): + """Test character count validation (2000 max)""" + builder = TextBuilder() + + # Add text approaching the limit + builder.text("x" * 2000) + + # Should work at exactly 2000 + result = builder.build() + assert len(result) == 2000 + + # Exceeding should raise error + builder2 = TextBuilder() + builder2.text("x" * 2001) + with pytest.raises(ValueError, match="exceeds 2000 character limit"): + builder2.build() + + def test_empty_builder(self): + """Test building with no content""" + builder = TextBuilder() + result = builder.build() + assert result == "" + + def test_invalid_ipa(self): + """Test validation of IPA pronunciation""" + builder = TextBuilder() + + # Should reject IPA with invalid characters + with pytest.raises(ValueError, match="invalid character"): + builder.pronunciation("word", 'invalid"quote') + + with pytest.raises(ValueError, match="invalid character"): + builder.pronunciation("word", "invalid\nline") + + def test_invalid_pause_duration(self): + """Test pause duration validation""" + builder = TextBuilder() + + # Too short + with pytest.raises(ValueError, match="at least 500ms"): + builder.pause(400) + + # Too long + with pytest.raises(ValueError, match="not exceed 5000ms"): + builder.pause(5001) + + # Not in 100ms increments + with pytest.raises(ValueError, match="100ms increments"): + builder.pause(550) + + def test_pause_boundary_values(self): + """Test pause at valid boundaries""" + builder = TextBuilder() + + # Minimum valid + result1 = builder.pause(500).build() + assert "{pause:500}" in result1 + + # Maximum valid + builder2 = TextBuilder() + result2 = builder2.pause(5000).build() + assert "{pause:5000}" in result2 + + +class TestAddPronunciation: + """Tests for the add_pronunciation function""" + + def test_basic_replacement(self): + """Test basic word replacement""" + text = "Take azathioprine twice daily." + result = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + assert "Take " in result + assert " twice daily." in result + + def test_multiple_replacements(self): + """Test replacing multiple words""" + text = "Take azathioprine twice daily with dupilumab injections." + text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") + + assert '"word": "azathioprine"' in text + assert '"word": "dupilumab"' in text + + def test_whole_word_only(self): + """Test that replacement only affects whole words""" + text = "The therapist prescribed therapy." + result = add_pronunciation(text, "The", "ðiː") + + # Should only replace "The", not "the" in "therapist" or "therapy" + assert result.count('"word"') == 1 + assert "therapist" in result + assert "therapy" in result + + def test_case_sensitive(self): + """Test that replacement is case-sensitive""" + text = "Take azathioprine. AZATHIOPRINE is different." + result = add_pronunciation(text, "azathioprine", "test") + + # Should only replace lowercase version (first occurrence) + assert result.count('"word"') == 1 + assert "AZATHIOPRINE" in result + + def test_word_not_found(self): + """Test replacement when word is not in text""" + text = "Hello world" + result = add_pronunciation(text, "missing", "test") + + # Text should be unchanged + assert result == text + + +class TestSsmlToDeepgram: + """Tests for SSML conversion""" + + def test_basic_phoneme(self): + """Test converting basic phoneme tag""" + ssml = 'azathioprine' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + + def test_basic_break(self): + """Test converting break tag (milliseconds)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + assert result == "{pause:500}" + + def test_break_seconds(self): + """Test converting break tag (seconds)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + assert result == "{pause:500}" + + def test_speak_wrapper(self): + """Test handling wrapper tag""" + ssml = 'Hello world' + result = ssml_to_deepgram(ssml) + + assert result == "Hello world" + + def test_complex_ssml(self): + """Test complex SSML with multiple elements""" + ssml = ''' + Take azathioprine + Do not exceed dosage. + ''' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert "{pause:500}" in result + assert "Do not exceed dosage." in result + + def test_multiple_phonemes(self): + """Test multiple phoneme tags""" + ssml = '''Take azathioprine + with dupilumab''' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert '"word": "dupilumab"' in result + + def test_plain_text(self): + """Test plain text without SSML tags""" + text = "Hello world" + result = ssml_to_deepgram(text) + + assert result == text + + def test_break_out_of_range(self): + """Test break with out-of-range duration (should round to valid)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + # Should round to nearest valid value (500ms) + assert "{pause:" in result + + +class TestFromSsml: + """Tests for TextBuilder.from_ssml() method""" + + def test_from_ssml_basic(self): + """Test parsing SSML into builder""" + ssml = 'Hello world' + builder = TextBuilder() + result = builder.from_ssml(ssml).build() + + assert "Hello world" in result + + def test_from_ssml_with_additional_text(self): + """Test mixing SSML parsing with additional builder methods""" + ssml = 'Take medicine' + builder = TextBuilder() + result = ( + builder + .from_ssml(ssml) + .pause(500) + .text(" Do not exceed dosage.") + .build() + ) + + assert '"word": "medicine"' in result + assert "{pause:500}" in result + assert "Do not exceed dosage." in result + + def test_from_ssml_counts_pronunciations(self): + """Test that from_ssml updates internal counters""" + # Create SSML with pronunciations + pronunciations = ''.join([ + f'word{i} ' + for i in range(500) + ]) + ssml = f'{pronunciations}' + + builder = TextBuilder() + builder.from_ssml(ssml) + + # Should hit the limit + with pytest.raises(ValueError, match="Maximum 500 pronunciations"): + builder.pronunciation("extra", "test") + + +class TestValidateIpa: + """Tests for IPA validation""" + + def test_valid_ipa(self): + """Test valid IPA strings""" + is_valid, msg = validate_ipa("ˌæzəˈθaɪəpriːn") + assert is_valid is True + assert msg == "" + + def test_empty_ipa(self): + """Test empty IPA string""" + is_valid, msg = validate_ipa("") + assert is_valid is False + assert "cannot be empty" in msg + + def test_invalid_characters(self): + """Test IPA with invalid characters""" + # Double quote + is_valid, msg = validate_ipa('test"quote') + assert is_valid is False + assert "invalid character" in msg + + # Newline + is_valid, msg = validate_ipa("test\nline") + assert is_valid is False + assert "invalid character" in msg + + def test_too_long(self): + """Test IPA exceeding length limit""" + is_valid, msg = validate_ipa("x" * 101) + assert is_valid is False + assert "exceeds 100 character limit" in msg + + def test_not_string(self): + """Test non-string IPA""" + is_valid, msg = validate_ipa(123) + assert is_valid is False + assert "must be a string" in msg + + +class TestValidatePause: + """Tests for pause validation""" + + def test_valid_pauses(self): + """Test valid pause durations""" + # Minimum + is_valid, msg = validate_pause(500) + assert is_valid is True + + # Maximum + is_valid, msg = validate_pause(5000) + assert is_valid is True + + # Mid-range + is_valid, msg = validate_pause(2500) + assert is_valid is True + + def test_too_short(self): + """Test pause below minimum""" + is_valid, msg = validate_pause(400) + assert is_valid is False + assert "at least 500ms" in msg + + def test_too_long(self): + """Test pause above maximum""" + is_valid, msg = validate_pause(5001) + assert is_valid is False + assert "not exceed 5000ms" in msg + + def test_invalid_increment(self): + """Test pause not in 100ms increments""" + is_valid, msg = validate_pause(550) + assert is_valid is False + assert "100ms increments" in msg + + def test_not_integer(self): + """Test non-integer pause""" + is_valid, msg = validate_pause(500.5) + assert is_valid is False + assert "must be an integer" in msg + + +class TestIntegration: + """Integration tests combining multiple features""" + + def test_medical_example(self): + """Test the medical prescription example from the spec""" + text = ( + TextBuilder() + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily with ") + .pronunciation("dupilumab", "duːˈpɪljuːmæb") + .text(" injections") + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + # Verify all components are present + assert "Take " in text + assert '"word": "azathioprine"' in text + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text + assert " twice daily with " in text + assert '"word": "dupilumab"' in text + assert '"pronounce": "duːˈpɪljuːmæb"' in text + assert " injections" in text + assert "{pause:500}" in text + assert " Do not exceed prescribed dosage." in text + + def test_ssml_migration(self): + """Test SSML to Deepgram migration workflow""" + ssml = ''' + Take azathioprine + Do not exceed dosage. + ''' + + # Method 1: Direct conversion + text1 = ssml_to_deepgram(ssml) + + # Method 2: Using builder + text2 = TextBuilder().from_ssml(ssml).build() + + # Both should produce similar results + assert '"word": "azathioprine"' in text1 + assert "{pause:500}" in text1 + assert '"word": "azathioprine"' in text2 + assert "{pause:500}" in text2 + + def test_builder_with_ssml_and_additions(self): + """Test the mixed usage example from the spec""" + some_imported_ssml = ''' + Take medicine + ''' + + text = ( + TextBuilder() + .from_ssml(some_imported_ssml) + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + assert '"word": "medicine"' in text + assert "{pause:500}" in text + assert " Do not exceed prescribed dosage." in text + + def test_standalone_function_workflow(self): + """Test using standalone add_pronunciation function""" + text = "Take azathioprine twice daily with dupilumab injections." + text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") + + assert '"word": "azathioprine"' in text + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text + assert '"word": "dupilumab"' in text + assert '"pronounce": "duːˈpɪljuːmæb"' in text + diff --git a/tests/custom/test_transport.py b/tests/custom/test_transport.py new file mode 100644 index 00000000..ba860fa5 --- /dev/null +++ b/tests/custom/test_transport.py @@ -0,0 +1,481 @@ +"""Tests for custom WebSocket transport support.""" + +import json +import sys +from typing import Any, Dict, Iterator, List +from unittest.mock import MagicMock + +import pytest + +from deepgram.transport import ( + AsyncTransport, + SyncTransport, + _AsyncTransportShim, + _SyncTransportShim, + _TARGET_MODULES, + install_transport, + restore_transport, +) + + +# --------------------------------------------------------------------------- +# Mock transport implementations +# --------------------------------------------------------------------------- + +class MockSyncTransport: + """Minimal sync transport that satisfies the SyncTransport protocol.""" + + def __init__(self, messages: List[str] = None): + self._messages = list(messages or []) + self._sent: List[Any] = [] + self._closed = False + + def send(self, data: Any) -> None: + self._sent.append(data) + + def recv(self) -> str: + if self._messages: + return self._messages.pop(0) + raise StopIteration + + def __iter__(self) -> Iterator: + return iter(self._messages) + + def close(self) -> None: + self._closed = True + + +class MockAsyncTransport: + """Minimal async transport that satisfies the AsyncTransport protocol.""" + + def __init__(self, messages: List[str] = None): + self._messages = list(messages or []) + self._sent: List[Any] = [] + self._closed = False + + async def send(self, data: Any) -> None: + self._sent.append(data) + + async def recv(self) -> str: + if self._messages: + return self._messages.pop(0) + raise StopAsyncIteration + + async def __aiter__(self): + for msg in self._messages: + yield msg + + async def close(self) -> None: + self._closed = True + + +# --------------------------------------------------------------------------- +# Fixtures +# --------------------------------------------------------------------------- + +@pytest.fixture(autouse=True) +def _restore_after_test(): + """Ensure transport patches are cleaned up after every test.""" + yield + restore_transport() + + +# --------------------------------------------------------------------------- +# Protocol conformance +# --------------------------------------------------------------------------- + +class TestProtocolConformance: + def test_sync_transport_protocol(self): + transport = MockSyncTransport() + assert isinstance(transport, SyncTransport) + + def test_async_transport_protocol(self): + transport = MockAsyncTransport() + assert isinstance(transport, AsyncTransport) + + def test_object_not_conforming_sync(self): + assert not isinstance(object(), SyncTransport) + + def test_object_not_conforming_async(self): + assert not isinstance(object(), AsyncTransport) + + +# --------------------------------------------------------------------------- +# Sync shim +# --------------------------------------------------------------------------- + +class TestSyncTransportShim: + def test_connect_calls_factory(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com", additional_headers={"Authorization": "token xyz"}) as t: + assert t is transport + + factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) + + def test_connect_closes_transport(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com"): + assert not transport._closed + + assert transport._closed + + def test_connect_default_headers(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com"): + pass + + factory.assert_called_once_with("wss://example.com", {}) + + +# --------------------------------------------------------------------------- +# Async shim +# --------------------------------------------------------------------------- + +class TestAsyncTransportShim: + async def test_connect_calls_factory(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com", extra_headers={"Authorization": "token xyz"}) as t: + assert t is transport + + factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) + + async def test_connect_closes_transport(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com"): + assert not transport._closed + + assert transport._closed + + async def test_connect_default_headers(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com"): + pass + + factory.assert_called_once_with("wss://example.com", {}) + + +# --------------------------------------------------------------------------- +# install_transport / restore_transport +# --------------------------------------------------------------------------- + +def _ensure_modules_loaded(): + """Force-import all target modules so they appear in sys.modules.""" + for mod_path in _TARGET_MODULES: + if mod_path not in sys.modules: + __import__(mod_path) + + +class TestInstallRestore: + def test_install_sync_patches_all_modules(self): + _ensure_modules_loaded() + + factory = MagicMock() + install_transport(sync_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert isinstance(mod.websockets_sync_client, _SyncTransportShim), ( + f"{mod_path}.websockets_sync_client was not patched" + ) + + def test_install_async_patches_all_modules(self): + _ensure_modules_loaded() + + factory = MagicMock() + install_transport(async_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_client_connect"): + assert isinstance(mod.websockets_client_connect, _AsyncTransportShim), ( + f"{mod_path}.websockets_client_connect was not patched" + ) + + def test_restore_undoes_patches(self): + _ensure_modules_loaded() + + # Capture originals + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = { + "sync": getattr(mod, "websockets_sync_client", None), + "async": getattr(mod, "websockets_client_connect", None), + } + + install_transport(sync_factory=MagicMock(), async_factory=MagicMock()) + restore_transport() + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path]["sync"] is not None: + assert mod.websockets_sync_client is originals[mod_path]["sync"], ( + f"{mod_path}.websockets_sync_client was not restored" + ) + if originals[mod_path]["async"] is not None: + assert mod.websockets_client_connect is originals[mod_path]["async"], ( + f"{mod_path}.websockets_client_connect was not restored" + ) + + def test_install_only_sync_leaves_async_untouched(self): + _ensure_modules_loaded() + + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = getattr(mod, "websockets_client_connect", None) + + install_transport(sync_factory=MagicMock()) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path] is not None: + assert mod.websockets_client_connect is originals[mod_path] + + def test_install_only_async_leaves_sync_untouched(self): + _ensure_modules_loaded() + + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = getattr(mod, "websockets_sync_client", None) + + install_transport(async_factory=MagicMock()) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path] is not None: + assert mod.websockets_sync_client is originals[mod_path] + + +# --------------------------------------------------------------------------- +# Conflict guard +# --------------------------------------------------------------------------- + +class TestConflictGuard: + def test_same_sync_factory_is_idempotent(self): + _ensure_modules_loaded() + factory = MagicMock() + install_transport(sync_factory=factory) + install_transport(sync_factory=factory) # should not raise + + def test_same_async_factory_is_idempotent(self): + _ensure_modules_loaded() + factory = MagicMock() + install_transport(async_factory=factory) + install_transport(async_factory=factory) # should not raise + + def test_different_sync_factory_raises(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + with pytest.raises(RuntimeError, match="different sync transport factory"): + install_transport(sync_factory=MagicMock()) + + def test_different_async_factory_raises(self): + _ensure_modules_loaded() + install_transport(async_factory=MagicMock()) + with pytest.raises(RuntimeError, match="different async transport factory"): + install_transport(async_factory=MagicMock()) + + def test_restore_then_reinstall_different_factory(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + restore_transport() + install_transport(sync_factory=MagicMock()) # should not raise + + def test_sync_and_async_factories_are_independent(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + install_transport(async_factory=MagicMock()) # should not raise + + +# --------------------------------------------------------------------------- +# End-to-end: sync listen with mock transport +# --------------------------------------------------------------------------- + +def _valid_metadata_json() -> str: + """Return a JSON string that matches the ListenV1Metadata Pydantic model.""" + return json.dumps({ + "type": "Metadata", + "transaction_key": "test-txn-key", + "request_id": "req-001", + "sha256": "abc123", + "created": "2024-01-01T00:00:00Z", + "duration": 1.5, + "channels": 1, + }) + + +class TestSyncEndToEnd: + def test_listen_v1_with_mock_transport(self): + """Verify a mock transport receives messages through the event system.""" + from deepgram.core.events import EventEmitterMixin, EventType + from deepgram.listen.v1.socket_client import V1SocketClient + + transcript_json = _valid_metadata_json() + + transport = MockSyncTransport(messages=[transcript_json]) + client = V1SocketClient(websocket=transport) + + received = [] + errors = [] + client.on(EventType.MESSAGE, lambda msg: received.append(msg)) + client.on(EventType.ERROR, lambda err: errors.append(err)) + + client.start_listening() + + assert len(errors) == 0 + assert len(received) == 1 + + def test_custom_transport_error_emits_error_event(self): + """When the transport raises, EventType.ERROR should fire.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import V1SocketClient + + class FailingTransport: + def send(self, data): pass + def recv(self): raise ConnectionError("boom") + def close(self): pass + def __iter__(self): + raise ConnectionError("boom") + + client = V1SocketClient(websocket=FailingTransport()) + + errors = [] + closed = [] + client.on(EventType.ERROR, lambda err: errors.append(err)) + client.on(EventType.CLOSE, lambda _: closed.append(True)) + + client.start_listening() + + assert len(errors) == 1 + assert isinstance(errors[0], ConnectionError) + assert len(closed) == 1 + + +# --------------------------------------------------------------------------- +# End-to-end: async listen with mock transport +# --------------------------------------------------------------------------- + +class TestAsyncEndToEnd: + async def test_listen_v1_async_with_mock_transport(self): + """Verify a mock async transport works through the event system.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import AsyncV1SocketClient + + transcript_json = _valid_metadata_json() + + class AsyncMockWS: + def __init__(self): + self._messages = [transcript_json] + + async def send(self, data): pass + async def recv(self): return self._messages.pop(0) + async def close(self): pass + + async def __aiter__(self): + for msg in list(self._messages): + yield msg + + transport = AsyncMockWS() + client = AsyncV1SocketClient(websocket=transport) + + received = [] + errors = [] + client.on(EventType.MESSAGE, lambda msg: received.append(msg)) + client.on(EventType.ERROR, lambda err: errors.append(err)) + + await client.start_listening() + + assert len(errors) == 0 + assert len(received) == 1 + + async def test_async_transport_error_emits_error_event(self): + """When the async transport raises, EventType.ERROR should fire.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import AsyncV1SocketClient + + class FailingAsyncTransport: + async def send(self, data): pass + async def recv(self): raise ConnectionError("async boom") + async def close(self): pass + + async def __aiter__(self): + raise ConnectionError("async boom") + yield # unreachable — makes this an async generator + + client = AsyncV1SocketClient(websocket=FailingAsyncTransport()) + + errors = [] + closed = [] + client.on(EventType.ERROR, lambda err: errors.append(err)) + client.on(EventType.CLOSE, lambda _: closed.append(True)) + + await client.start_listening() + + assert len(errors) == 1 + assert isinstance(errors[0], ConnectionError) + assert len(closed) == 1 + + +# --------------------------------------------------------------------------- +# DeepgramClient construction triggers patching +# --------------------------------------------------------------------------- + +class TestClientConstruction: + def test_deepgram_client_installs_sync_transport(self): + _ensure_modules_loaded() + + factory = MagicMock() + from deepgram.client import DeepgramClient + DeepgramClient(api_key="test-key", transport_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert isinstance(mod.websockets_sync_client, _SyncTransportShim) + + def test_deepgram_client_without_factory_does_not_patch(self): + _ensure_modules_loaded() + + # Ensure clean state + restore_transport() + + from deepgram.client import DeepgramClient + DeepgramClient(api_key="test-key") + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert not isinstance(mod.websockets_sync_client, _SyncTransportShim) + + def test_async_deepgram_client_installs_async_transport(self): + _ensure_modules_loaded() + + factory = MagicMock() + from deepgram.client import AsyncDeepgramClient + AsyncDeepgramClient(api_key="test-key", transport_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_client_connect"): + assert isinstance(mod.websockets_client_connect, _AsyncTransportShim) From 8aaf78a3df98450c76ed5c0a69581f9f5de4e562 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:37:52 +0000 Subject: [PATCH 03/11] SDK regeneration --- .fern/metadata.json | 2 +- pyproject.toml | 2 +- src/deepgram/agent/v1/socket_client.py | 38 +- src/deepgram/core/client_wrapper.py | 2 +- src/deepgram/listen/v1/socket_client.py | 30 +- src/deepgram/listen/v2/socket_client.py | 14 +- src/deepgram/speak/v1/socket_client.py | 30 +- tests/custom/test_text_builder.py | 500 ------------------------ tests/custom/test_transport.py | 481 ----------------------- 9 files changed, 53 insertions(+), 1046 deletions(-) delete mode 100644 tests/custom/test_text_builder.py delete mode 100644 tests/custom/test_transport.py diff --git a/.fern/metadata.json b/.fern/metadata.json index 8eb0bbad..74bdbd67 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -16,5 +16,5 @@ "skip_validation": true } }, - "sdkVersion": "0.0.333" + "sdkVersion": "0.0.334" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index a11551e5..5fbcd15c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "deepgram-sdk" -version = "6.0.1" +version = "0.0.334" description = "" readme = "README.md" authors = [] diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index 56dd49fe..53428363 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -33,26 +35,6 @@ except ImportError: from websockets import WebSocketClientProtocol # type: ignore -def _sanitize_numeric_types(obj: typing.Any) -> typing.Any: - """ - Recursively convert float values that are whole numbers to int. - - Workaround for Fern-generated models that type integer API fields - (like sample_rate) as float, causing JSON serialization to produce - values like 44100.0 instead of 44100. The Deepgram API rejects - float representations of integer fields. - - See: https://github.com/deepgram/internal-api-specs/issues/205 - """ - if isinstance(obj, dict): - return {k: _sanitize_numeric_types(v) for k, v in obj.items()} - elif isinstance(obj, list): - return [_sanitize_numeric_types(item) for item in obj] - elif isinstance(obj, float) and obj.is_integer(): - return int(obj) - return obj - - V1SocketClientResponse = typing.Union[ AgentV1ReceiveFunctionCallResponse, AgentV1PromptUpdated, @@ -103,7 +85,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -143,12 +125,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp """ await self._send_model(message) - async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: + async def send_keep_alive(self, message: AgentV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - await self._send_model(message or AgentV1KeepAlive()) + await self._send_model(message) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -186,7 +168,7 @@ async def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - await self._send(_sanitize_numeric_types(data.dict())) + await self._send(data.dict()) class V1SocketClient(EventEmitterMixin): @@ -220,7 +202,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -260,12 +242,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) """ self._send_model(message) - def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: + def send_keep_alive(self, message: AgentV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - self._send_model(message or AgentV1KeepAlive()) + self._send_model(message) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -303,4 +285,4 @@ def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - self._send(_sanitize_numeric_types(data.dict())) + self._send(data.dict()) diff --git a/src/deepgram/core/client_wrapper.py b/src/deepgram/core/client_wrapper.py index 18b04517..4fd5489f 100644 --- a/src/deepgram/core/client_wrapper.py +++ b/src/deepgram/core/client_wrapper.py @@ -29,7 +29,7 @@ def get_headers(self) -> typing.Dict[str, str]: "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "deepgram-sdk", - "X-Fern-SDK-Version": "6.0.1", + "X-Fern-SDK-Version": "0.0.334", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Token {self.api_key}" diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index ce948284..1c186616 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -53,7 +55,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -65,26 +67,26 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: + async def send_finalize(self, message: ListenV1Finalize) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - await self._send_model(message or ListenV1Finalize(type="Finalize")) + await self._send_model(message) - async def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: + async def send_close_stream(self, message: ListenV1CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - await self._send_model(message or ListenV1CloseStream(type="CloseStream")) + await self._send_model(message) - async def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: + async def send_keep_alive(self, message: ListenV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - await self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) + await self._send_model(message) async def recv(self) -> V1SocketClientResponse: """ @@ -142,7 +144,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -154,26 +156,26 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: + def send_finalize(self, message: ListenV1Finalize) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - self._send_model(message or ListenV1Finalize(type="Finalize")) + self._send_model(message) - def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: + def send_close_stream(self, message: ListenV1CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - self._send_model(message or ListenV1CloseStream(type="CloseStream")) + self._send_model(message) - def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: + def send_keep_alive(self, message: ListenV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) + self._send_model(message) def recv(self) -> V1SocketClientResponse: """ diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 09935ff8..72bc94f9 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -50,7 +52,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -62,12 +64,12 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: + async def send_close_stream(self, message: ListenV2CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - await self._send_model(message or ListenV2CloseStream(type="CloseStream")) + await self._send_model(message) async def recv(self) -> V2SocketClientResponse: """ @@ -125,7 +127,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -137,12 +139,12 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: + def send_close_stream(self, message: ListenV2CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - self._send_model(message or ListenV2CloseStream(type="CloseStream")) + self._send_model(message) def recv(self) -> V2SocketClientResponse: """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index e04280bf..cac0ae3c 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -54,7 +56,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -66,26 +68,26 @@ async def send_text(self, message: SpeakV1Text) -> None: """ await self._send_model(message) - async def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: + async def send_flush(self, message: SpeakV1Flush) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - await self._send_model(message or SpeakV1Flush(type="Flush")) + await self._send_model(message) - async def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: + async def send_clear(self, message: SpeakV1Clear) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - await self._send_model(message or SpeakV1Clear(type="Clear")) + await self._send_model(message) - async def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: + async def send_close(self, message: SpeakV1Close) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - await self._send_model(message or SpeakV1Close(type="Close")) + await self._send_model(message) async def recv(self) -> V1SocketClientResponse: """ @@ -143,7 +145,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -155,26 +157,26 @@ def send_text(self, message: SpeakV1Text) -> None: """ self._send_model(message) - def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: + def send_flush(self, message: SpeakV1Flush) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - self._send_model(message or SpeakV1Flush(type="Flush")) + self._send_model(message) - def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: + def send_clear(self, message: SpeakV1Clear) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - self._send_model(message or SpeakV1Clear(type="Clear")) + self._send_model(message) - def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: + def send_close(self, message: SpeakV1Close) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - self._send_model(message or SpeakV1Close(type="Close")) + self._send_model(message) def recv(self) -> V1SocketClientResponse: """ diff --git a/tests/custom/test_text_builder.py b/tests/custom/test_text_builder.py deleted file mode 100644 index 77a7ed1b..00000000 --- a/tests/custom/test_text_builder.py +++ /dev/null @@ -1,500 +0,0 @@ -""" -Tests for TextBuilder and TTS helper utilities -""" - -import pytest -from deepgram.helpers import ( - TextBuilder, - add_pronunciation, - ssml_to_deepgram, - validate_ipa, - validate_pause, -) - - -class TestTextBuilder: - """Tests for the TextBuilder class""" - - def test_basic_text(self): - """Test adding plain text""" - builder = TextBuilder() - result = builder.text("Hello world").build() - assert result == "Hello world" - - def test_multiple_text_parts(self): - """Test chaining multiple text parts""" - builder = TextBuilder() - result = builder.text("Hello ").text("world").build() - assert result == "Hello world" - - def test_pronunciation(self): - """Test adding pronunciation""" - builder = TextBuilder() - result = builder.pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn").build() - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - - def test_text_with_pronunciation(self): - """Test mixing text and pronunciation""" - builder = TextBuilder() - result = ( - builder - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily") - .build() - ) - assert "Take " in result - assert '"word": "azathioprine"' in result - assert " twice daily" in result - - def test_pause(self): - """Test adding pause""" - builder = TextBuilder() - result = builder.pause(500).build() - assert result == "{pause:500}" - - def test_text_with_pause(self): - """Test mixing text and pause""" - builder = TextBuilder() - result = ( - builder - .text("Hello") - .pause(1000) - .text("world") - .build() - ) - assert result == "Hello{pause:1000}world" - - def test_complex_chain(self): - """Test complex chaining with all features""" - builder = TextBuilder() - result = ( - builder - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily with ") - .pronunciation("dupilumab", "duːˈpɪljuːmæb") - .text(" injections") - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - assert "Take " in result - assert '"word": "azathioprine"' in result - assert " twice daily with " in result - assert '"word": "dupilumab"' in result - assert " injections" in result - assert "{pause:500}" in result - assert " Do not exceed prescribed dosage." in result - - def test_pronunciation_limit(self): - """Test pronunciation count limit (500 max)""" - builder = TextBuilder() - - # Add 500 pronunciations (should work) - for i in range(500): - builder.pronunciation(f"word{i}", "test") - - # 501st should raise error - with pytest.raises(ValueError, match="Maximum 500 pronunciations"): - builder.pronunciation("extra", "test") - - def test_pause_limit(self): - """Test pause count limit (50 max)""" - builder = TextBuilder() - - # Add 50 pauses (should work) - for i in range(50): - builder.pause(500) - - # 51st should raise error - with pytest.raises(ValueError, match="Maximum 50 pauses"): - builder.pause(500) - - def test_character_limit(self): - """Test character count validation (2000 max)""" - builder = TextBuilder() - - # Add text approaching the limit - builder.text("x" * 2000) - - # Should work at exactly 2000 - result = builder.build() - assert len(result) == 2000 - - # Exceeding should raise error - builder2 = TextBuilder() - builder2.text("x" * 2001) - with pytest.raises(ValueError, match="exceeds 2000 character limit"): - builder2.build() - - def test_empty_builder(self): - """Test building with no content""" - builder = TextBuilder() - result = builder.build() - assert result == "" - - def test_invalid_ipa(self): - """Test validation of IPA pronunciation""" - builder = TextBuilder() - - # Should reject IPA with invalid characters - with pytest.raises(ValueError, match="invalid character"): - builder.pronunciation("word", 'invalid"quote') - - with pytest.raises(ValueError, match="invalid character"): - builder.pronunciation("word", "invalid\nline") - - def test_invalid_pause_duration(self): - """Test pause duration validation""" - builder = TextBuilder() - - # Too short - with pytest.raises(ValueError, match="at least 500ms"): - builder.pause(400) - - # Too long - with pytest.raises(ValueError, match="not exceed 5000ms"): - builder.pause(5001) - - # Not in 100ms increments - with pytest.raises(ValueError, match="100ms increments"): - builder.pause(550) - - def test_pause_boundary_values(self): - """Test pause at valid boundaries""" - builder = TextBuilder() - - # Minimum valid - result1 = builder.pause(500).build() - assert "{pause:500}" in result1 - - # Maximum valid - builder2 = TextBuilder() - result2 = builder2.pause(5000).build() - assert "{pause:5000}" in result2 - - -class TestAddPronunciation: - """Tests for the add_pronunciation function""" - - def test_basic_replacement(self): - """Test basic word replacement""" - text = "Take azathioprine twice daily." - result = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - assert "Take " in result - assert " twice daily." in result - - def test_multiple_replacements(self): - """Test replacing multiple words""" - text = "Take azathioprine twice daily with dupilumab injections." - text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") - - assert '"word": "azathioprine"' in text - assert '"word": "dupilumab"' in text - - def test_whole_word_only(self): - """Test that replacement only affects whole words""" - text = "The therapist prescribed therapy." - result = add_pronunciation(text, "The", "ðiː") - - # Should only replace "The", not "the" in "therapist" or "therapy" - assert result.count('"word"') == 1 - assert "therapist" in result - assert "therapy" in result - - def test_case_sensitive(self): - """Test that replacement is case-sensitive""" - text = "Take azathioprine. AZATHIOPRINE is different." - result = add_pronunciation(text, "azathioprine", "test") - - # Should only replace lowercase version (first occurrence) - assert result.count('"word"') == 1 - assert "AZATHIOPRINE" in result - - def test_word_not_found(self): - """Test replacement when word is not in text""" - text = "Hello world" - result = add_pronunciation(text, "missing", "test") - - # Text should be unchanged - assert result == text - - -class TestSsmlToDeepgram: - """Tests for SSML conversion""" - - def test_basic_phoneme(self): - """Test converting basic phoneme tag""" - ssml = 'azathioprine' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result - - def test_basic_break(self): - """Test converting break tag (milliseconds)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - assert result == "{pause:500}" - - def test_break_seconds(self): - """Test converting break tag (seconds)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - assert result == "{pause:500}" - - def test_speak_wrapper(self): - """Test handling wrapper tag""" - ssml = 'Hello world' - result = ssml_to_deepgram(ssml) - - assert result == "Hello world" - - def test_complex_ssml(self): - """Test complex SSML with multiple elements""" - ssml = ''' - Take azathioprine - Do not exceed dosage. - ''' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert "{pause:500}" in result - assert "Do not exceed dosage." in result - - def test_multiple_phonemes(self): - """Test multiple phoneme tags""" - ssml = '''Take azathioprine - with dupilumab''' - result = ssml_to_deepgram(ssml) - - assert '"word": "azathioprine"' in result - assert '"word": "dupilumab"' in result - - def test_plain_text(self): - """Test plain text without SSML tags""" - text = "Hello world" - result = ssml_to_deepgram(text) - - assert result == text - - def test_break_out_of_range(self): - """Test break with out-of-range duration (should round to valid)""" - ssml = '' - result = ssml_to_deepgram(ssml) - - # Should round to nearest valid value (500ms) - assert "{pause:" in result - - -class TestFromSsml: - """Tests for TextBuilder.from_ssml() method""" - - def test_from_ssml_basic(self): - """Test parsing SSML into builder""" - ssml = 'Hello world' - builder = TextBuilder() - result = builder.from_ssml(ssml).build() - - assert "Hello world" in result - - def test_from_ssml_with_additional_text(self): - """Test mixing SSML parsing with additional builder methods""" - ssml = 'Take medicine' - builder = TextBuilder() - result = ( - builder - .from_ssml(ssml) - .pause(500) - .text(" Do not exceed dosage.") - .build() - ) - - assert '"word": "medicine"' in result - assert "{pause:500}" in result - assert "Do not exceed dosage." in result - - def test_from_ssml_counts_pronunciations(self): - """Test that from_ssml updates internal counters""" - # Create SSML with pronunciations - pronunciations = ''.join([ - f'word{i} ' - for i in range(500) - ]) - ssml = f'{pronunciations}' - - builder = TextBuilder() - builder.from_ssml(ssml) - - # Should hit the limit - with pytest.raises(ValueError, match="Maximum 500 pronunciations"): - builder.pronunciation("extra", "test") - - -class TestValidateIpa: - """Tests for IPA validation""" - - def test_valid_ipa(self): - """Test valid IPA strings""" - is_valid, msg = validate_ipa("ˌæzəˈθaɪəpriːn") - assert is_valid is True - assert msg == "" - - def test_empty_ipa(self): - """Test empty IPA string""" - is_valid, msg = validate_ipa("") - assert is_valid is False - assert "cannot be empty" in msg - - def test_invalid_characters(self): - """Test IPA with invalid characters""" - # Double quote - is_valid, msg = validate_ipa('test"quote') - assert is_valid is False - assert "invalid character" in msg - - # Newline - is_valid, msg = validate_ipa("test\nline") - assert is_valid is False - assert "invalid character" in msg - - def test_too_long(self): - """Test IPA exceeding length limit""" - is_valid, msg = validate_ipa("x" * 101) - assert is_valid is False - assert "exceeds 100 character limit" in msg - - def test_not_string(self): - """Test non-string IPA""" - is_valid, msg = validate_ipa(123) - assert is_valid is False - assert "must be a string" in msg - - -class TestValidatePause: - """Tests for pause validation""" - - def test_valid_pauses(self): - """Test valid pause durations""" - # Minimum - is_valid, msg = validate_pause(500) - assert is_valid is True - - # Maximum - is_valid, msg = validate_pause(5000) - assert is_valid is True - - # Mid-range - is_valid, msg = validate_pause(2500) - assert is_valid is True - - def test_too_short(self): - """Test pause below minimum""" - is_valid, msg = validate_pause(400) - assert is_valid is False - assert "at least 500ms" in msg - - def test_too_long(self): - """Test pause above maximum""" - is_valid, msg = validate_pause(5001) - assert is_valid is False - assert "not exceed 5000ms" in msg - - def test_invalid_increment(self): - """Test pause not in 100ms increments""" - is_valid, msg = validate_pause(550) - assert is_valid is False - assert "100ms increments" in msg - - def test_not_integer(self): - """Test non-integer pause""" - is_valid, msg = validate_pause(500.5) - assert is_valid is False - assert "must be an integer" in msg - - -class TestIntegration: - """Integration tests combining multiple features""" - - def test_medical_example(self): - """Test the medical prescription example from the spec""" - text = ( - TextBuilder() - .text("Take ") - .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") - .text(" twice daily with ") - .pronunciation("dupilumab", "duːˈpɪljuːmæb") - .text(" injections") - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - # Verify all components are present - assert "Take " in text - assert '"word": "azathioprine"' in text - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text - assert " twice daily with " in text - assert '"word": "dupilumab"' in text - assert '"pronounce": "duːˈpɪljuːmæb"' in text - assert " injections" in text - assert "{pause:500}" in text - assert " Do not exceed prescribed dosage." in text - - def test_ssml_migration(self): - """Test SSML to Deepgram migration workflow""" - ssml = ''' - Take azathioprine - Do not exceed dosage. - ''' - - # Method 1: Direct conversion - text1 = ssml_to_deepgram(ssml) - - # Method 2: Using builder - text2 = TextBuilder().from_ssml(ssml).build() - - # Both should produce similar results - assert '"word": "azathioprine"' in text1 - assert "{pause:500}" in text1 - assert '"word": "azathioprine"' in text2 - assert "{pause:500}" in text2 - - def test_builder_with_ssml_and_additions(self): - """Test the mixed usage example from the spec""" - some_imported_ssml = ''' - Take medicine - ''' - - text = ( - TextBuilder() - .from_ssml(some_imported_ssml) - .pause(500) - .text(" Do not exceed prescribed dosage.") - .build() - ) - - assert '"word": "medicine"' in text - assert "{pause:500}" in text - assert " Do not exceed prescribed dosage." in text - - def test_standalone_function_workflow(self): - """Test using standalone add_pronunciation function""" - text = "Take azathioprine twice daily with dupilumab injections." - text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") - text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") - - assert '"word": "azathioprine"' in text - assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text - assert '"word": "dupilumab"' in text - assert '"pronounce": "duːˈpɪljuːmæb"' in text - diff --git a/tests/custom/test_transport.py b/tests/custom/test_transport.py deleted file mode 100644 index ba860fa5..00000000 --- a/tests/custom/test_transport.py +++ /dev/null @@ -1,481 +0,0 @@ -"""Tests for custom WebSocket transport support.""" - -import json -import sys -from typing import Any, Dict, Iterator, List -from unittest.mock import MagicMock - -import pytest - -from deepgram.transport import ( - AsyncTransport, - SyncTransport, - _AsyncTransportShim, - _SyncTransportShim, - _TARGET_MODULES, - install_transport, - restore_transport, -) - - -# --------------------------------------------------------------------------- -# Mock transport implementations -# --------------------------------------------------------------------------- - -class MockSyncTransport: - """Minimal sync transport that satisfies the SyncTransport protocol.""" - - def __init__(self, messages: List[str] = None): - self._messages = list(messages or []) - self._sent: List[Any] = [] - self._closed = False - - def send(self, data: Any) -> None: - self._sent.append(data) - - def recv(self) -> str: - if self._messages: - return self._messages.pop(0) - raise StopIteration - - def __iter__(self) -> Iterator: - return iter(self._messages) - - def close(self) -> None: - self._closed = True - - -class MockAsyncTransport: - """Minimal async transport that satisfies the AsyncTransport protocol.""" - - def __init__(self, messages: List[str] = None): - self._messages = list(messages or []) - self._sent: List[Any] = [] - self._closed = False - - async def send(self, data: Any) -> None: - self._sent.append(data) - - async def recv(self) -> str: - if self._messages: - return self._messages.pop(0) - raise StopAsyncIteration - - async def __aiter__(self): - for msg in self._messages: - yield msg - - async def close(self) -> None: - self._closed = True - - -# --------------------------------------------------------------------------- -# Fixtures -# --------------------------------------------------------------------------- - -@pytest.fixture(autouse=True) -def _restore_after_test(): - """Ensure transport patches are cleaned up after every test.""" - yield - restore_transport() - - -# --------------------------------------------------------------------------- -# Protocol conformance -# --------------------------------------------------------------------------- - -class TestProtocolConformance: - def test_sync_transport_protocol(self): - transport = MockSyncTransport() - assert isinstance(transport, SyncTransport) - - def test_async_transport_protocol(self): - transport = MockAsyncTransport() - assert isinstance(transport, AsyncTransport) - - def test_object_not_conforming_sync(self): - assert not isinstance(object(), SyncTransport) - - def test_object_not_conforming_async(self): - assert not isinstance(object(), AsyncTransport) - - -# --------------------------------------------------------------------------- -# Sync shim -# --------------------------------------------------------------------------- - -class TestSyncTransportShim: - def test_connect_calls_factory(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com", additional_headers={"Authorization": "token xyz"}) as t: - assert t is transport - - factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) - - def test_connect_closes_transport(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com"): - assert not transport._closed - - assert transport._closed - - def test_connect_default_headers(self): - transport = MockSyncTransport() - factory = MagicMock(return_value=transport) - shim = _SyncTransportShim(factory) - - with shim.connect("wss://example.com"): - pass - - factory.assert_called_once_with("wss://example.com", {}) - - -# --------------------------------------------------------------------------- -# Async shim -# --------------------------------------------------------------------------- - -class TestAsyncTransportShim: - async def test_connect_calls_factory(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com", extra_headers={"Authorization": "token xyz"}) as t: - assert t is transport - - factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) - - async def test_connect_closes_transport(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com"): - assert not transport._closed - - assert transport._closed - - async def test_connect_default_headers(self): - transport = MockAsyncTransport() - factory = MagicMock(return_value=transport) - shim = _AsyncTransportShim(factory) - - async with shim("wss://example.com"): - pass - - factory.assert_called_once_with("wss://example.com", {}) - - -# --------------------------------------------------------------------------- -# install_transport / restore_transport -# --------------------------------------------------------------------------- - -def _ensure_modules_loaded(): - """Force-import all target modules so they appear in sys.modules.""" - for mod_path in _TARGET_MODULES: - if mod_path not in sys.modules: - __import__(mod_path) - - -class TestInstallRestore: - def test_install_sync_patches_all_modules(self): - _ensure_modules_loaded() - - factory = MagicMock() - install_transport(sync_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert isinstance(mod.websockets_sync_client, _SyncTransportShim), ( - f"{mod_path}.websockets_sync_client was not patched" - ) - - def test_install_async_patches_all_modules(self): - _ensure_modules_loaded() - - factory = MagicMock() - install_transport(async_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_client_connect"): - assert isinstance(mod.websockets_client_connect, _AsyncTransportShim), ( - f"{mod_path}.websockets_client_connect was not patched" - ) - - def test_restore_undoes_patches(self): - _ensure_modules_loaded() - - # Capture originals - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = { - "sync": getattr(mod, "websockets_sync_client", None), - "async": getattr(mod, "websockets_client_connect", None), - } - - install_transport(sync_factory=MagicMock(), async_factory=MagicMock()) - restore_transport() - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path]["sync"] is not None: - assert mod.websockets_sync_client is originals[mod_path]["sync"], ( - f"{mod_path}.websockets_sync_client was not restored" - ) - if originals[mod_path]["async"] is not None: - assert mod.websockets_client_connect is originals[mod_path]["async"], ( - f"{mod_path}.websockets_client_connect was not restored" - ) - - def test_install_only_sync_leaves_async_untouched(self): - _ensure_modules_loaded() - - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = getattr(mod, "websockets_client_connect", None) - - install_transport(sync_factory=MagicMock()) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path] is not None: - assert mod.websockets_client_connect is originals[mod_path] - - def test_install_only_async_leaves_sync_untouched(self): - _ensure_modules_loaded() - - originals = {} - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - originals[mod_path] = getattr(mod, "websockets_sync_client", None) - - install_transport(async_factory=MagicMock()) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if originals[mod_path] is not None: - assert mod.websockets_sync_client is originals[mod_path] - - -# --------------------------------------------------------------------------- -# Conflict guard -# --------------------------------------------------------------------------- - -class TestConflictGuard: - def test_same_sync_factory_is_idempotent(self): - _ensure_modules_loaded() - factory = MagicMock() - install_transport(sync_factory=factory) - install_transport(sync_factory=factory) # should not raise - - def test_same_async_factory_is_idempotent(self): - _ensure_modules_loaded() - factory = MagicMock() - install_transport(async_factory=factory) - install_transport(async_factory=factory) # should not raise - - def test_different_sync_factory_raises(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - with pytest.raises(RuntimeError, match="different sync transport factory"): - install_transport(sync_factory=MagicMock()) - - def test_different_async_factory_raises(self): - _ensure_modules_loaded() - install_transport(async_factory=MagicMock()) - with pytest.raises(RuntimeError, match="different async transport factory"): - install_transport(async_factory=MagicMock()) - - def test_restore_then_reinstall_different_factory(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - restore_transport() - install_transport(sync_factory=MagicMock()) # should not raise - - def test_sync_and_async_factories_are_independent(self): - _ensure_modules_loaded() - install_transport(sync_factory=MagicMock()) - install_transport(async_factory=MagicMock()) # should not raise - - -# --------------------------------------------------------------------------- -# End-to-end: sync listen with mock transport -# --------------------------------------------------------------------------- - -def _valid_metadata_json() -> str: - """Return a JSON string that matches the ListenV1Metadata Pydantic model.""" - return json.dumps({ - "type": "Metadata", - "transaction_key": "test-txn-key", - "request_id": "req-001", - "sha256": "abc123", - "created": "2024-01-01T00:00:00Z", - "duration": 1.5, - "channels": 1, - }) - - -class TestSyncEndToEnd: - def test_listen_v1_with_mock_transport(self): - """Verify a mock transport receives messages through the event system.""" - from deepgram.core.events import EventEmitterMixin, EventType - from deepgram.listen.v1.socket_client import V1SocketClient - - transcript_json = _valid_metadata_json() - - transport = MockSyncTransport(messages=[transcript_json]) - client = V1SocketClient(websocket=transport) - - received = [] - errors = [] - client.on(EventType.MESSAGE, lambda msg: received.append(msg)) - client.on(EventType.ERROR, lambda err: errors.append(err)) - - client.start_listening() - - assert len(errors) == 0 - assert len(received) == 1 - - def test_custom_transport_error_emits_error_event(self): - """When the transport raises, EventType.ERROR should fire.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import V1SocketClient - - class FailingTransport: - def send(self, data): pass - def recv(self): raise ConnectionError("boom") - def close(self): pass - def __iter__(self): - raise ConnectionError("boom") - - client = V1SocketClient(websocket=FailingTransport()) - - errors = [] - closed = [] - client.on(EventType.ERROR, lambda err: errors.append(err)) - client.on(EventType.CLOSE, lambda _: closed.append(True)) - - client.start_listening() - - assert len(errors) == 1 - assert isinstance(errors[0], ConnectionError) - assert len(closed) == 1 - - -# --------------------------------------------------------------------------- -# End-to-end: async listen with mock transport -# --------------------------------------------------------------------------- - -class TestAsyncEndToEnd: - async def test_listen_v1_async_with_mock_transport(self): - """Verify a mock async transport works through the event system.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import AsyncV1SocketClient - - transcript_json = _valid_metadata_json() - - class AsyncMockWS: - def __init__(self): - self._messages = [transcript_json] - - async def send(self, data): pass - async def recv(self): return self._messages.pop(0) - async def close(self): pass - - async def __aiter__(self): - for msg in list(self._messages): - yield msg - - transport = AsyncMockWS() - client = AsyncV1SocketClient(websocket=transport) - - received = [] - errors = [] - client.on(EventType.MESSAGE, lambda msg: received.append(msg)) - client.on(EventType.ERROR, lambda err: errors.append(err)) - - await client.start_listening() - - assert len(errors) == 0 - assert len(received) == 1 - - async def test_async_transport_error_emits_error_event(self): - """When the async transport raises, EventType.ERROR should fire.""" - from deepgram.core.events import EventType - from deepgram.listen.v1.socket_client import AsyncV1SocketClient - - class FailingAsyncTransport: - async def send(self, data): pass - async def recv(self): raise ConnectionError("async boom") - async def close(self): pass - - async def __aiter__(self): - raise ConnectionError("async boom") - yield # unreachable — makes this an async generator - - client = AsyncV1SocketClient(websocket=FailingAsyncTransport()) - - errors = [] - closed = [] - client.on(EventType.ERROR, lambda err: errors.append(err)) - client.on(EventType.CLOSE, lambda _: closed.append(True)) - - await client.start_listening() - - assert len(errors) == 1 - assert isinstance(errors[0], ConnectionError) - assert len(closed) == 1 - - -# --------------------------------------------------------------------------- -# DeepgramClient construction triggers patching -# --------------------------------------------------------------------------- - -class TestClientConstruction: - def test_deepgram_client_installs_sync_transport(self): - _ensure_modules_loaded() - - factory = MagicMock() - from deepgram.client import DeepgramClient - DeepgramClient(api_key="test-key", transport_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert isinstance(mod.websockets_sync_client, _SyncTransportShim) - - def test_deepgram_client_without_factory_does_not_patch(self): - _ensure_modules_loaded() - - # Ensure clean state - restore_transport() - - from deepgram.client import DeepgramClient - DeepgramClient(api_key="test-key") - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_sync_client"): - assert not isinstance(mod.websockets_sync_client, _SyncTransportShim) - - def test_async_deepgram_client_installs_async_transport(self): - _ensure_modules_loaded() - - factory = MagicMock() - from deepgram.client import AsyncDeepgramClient - AsyncDeepgramClient(api_key="test-key", transport_factory=factory) - - for mod_path in _TARGET_MODULES: - mod = sys.modules[mod_path] - if hasattr(mod, "websockets_client_connect"): - assert isinstance(mod.websockets_client_connect, _AsyncTransportShim) From af1f5716e6f9e059658ea5f6223ad327019b54a7 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 12:39:23 +0000 Subject: [PATCH 04/11] Revert "SDK regeneration" This reverts commit 8aaf78a3df98450c76ed5c0a69581f9f5de4e562. --- .fern/metadata.json | 2 +- pyproject.toml | 2 +- src/deepgram/agent/v1/socket_client.py | 38 +- src/deepgram/core/client_wrapper.py | 2 +- src/deepgram/listen/v1/socket_client.py | 30 +- src/deepgram/listen/v2/socket_client.py | 14 +- src/deepgram/speak/v1/socket_client.py | 30 +- tests/custom/test_text_builder.py | 500 ++++++++++++++++++++++++ tests/custom/test_transport.py | 481 +++++++++++++++++++++++ 9 files changed, 1046 insertions(+), 53 deletions(-) create mode 100644 tests/custom/test_text_builder.py create mode 100644 tests/custom/test_transport.py diff --git a/.fern/metadata.json b/.fern/metadata.json index 74bdbd67..8eb0bbad 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -16,5 +16,5 @@ "skip_validation": true } }, - "sdkVersion": "0.0.334" + "sdkVersion": "0.0.333" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5fbcd15c..a11551e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "deepgram-sdk" -version = "0.0.334" +version = "6.0.1" description = "" readme = "README.md" authors = [] diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index 53428363..56dd49fe 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -2,9 +2,7 @@ import json import typing -from json.decoder import JSONDecodeError -import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -35,6 +33,26 @@ except ImportError: from websockets import WebSocketClientProtocol # type: ignore +def _sanitize_numeric_types(obj: typing.Any) -> typing.Any: + """ + Recursively convert float values that are whole numbers to int. + + Workaround for Fern-generated models that type integer API fields + (like sample_rate) as float, causing JSON serialization to produce + values like 44100.0 instead of 44100. The Deepgram API rejects + float representations of integer fields. + + See: https://github.com/deepgram/internal-api-specs/issues/205 + """ + if isinstance(obj, dict): + return {k: _sanitize_numeric_types(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [_sanitize_numeric_types(item) for item in obj] + elif isinstance(obj, float) and obj.is_integer(): + return int(obj) + return obj + + V1SocketClientResponse = typing.Union[ AgentV1ReceiveFunctionCallResponse, AgentV1PromptUpdated, @@ -85,7 +103,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -125,12 +143,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp """ await self._send_model(message) - async def send_keep_alive(self, message: AgentV1KeepAlive) -> None: + async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - await self._send_model(message) + await self._send_model(message or AgentV1KeepAlive()) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -168,7 +186,7 @@ async def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - await self._send(data.dict()) + await self._send(_sanitize_numeric_types(data.dict())) class V1SocketClient(EventEmitterMixin): @@ -202,7 +220,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -242,12 +260,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) """ self._send_model(message) - def send_keep_alive(self, message: AgentV1KeepAlive) -> None: + def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - self._send_model(message) + self._send_model(message or AgentV1KeepAlive()) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -285,4 +303,4 @@ def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - self._send(data.dict()) + self._send(_sanitize_numeric_types(data.dict())) diff --git a/src/deepgram/core/client_wrapper.py b/src/deepgram/core/client_wrapper.py index 4fd5489f..18b04517 100644 --- a/src/deepgram/core/client_wrapper.py +++ b/src/deepgram/core/client_wrapper.py @@ -29,7 +29,7 @@ def get_headers(self) -> typing.Dict[str, str]: "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "deepgram-sdk", - "X-Fern-SDK-Version": "0.0.334", + "X-Fern-SDK-Version": "6.0.1", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Token {self.api_key}" diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index 1c186616..ce948284 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -2,9 +2,7 @@ import json import typing -from json.decoder import JSONDecodeError -import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -55,7 +53,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -67,26 +65,26 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_finalize(self, message: ListenV1Finalize) -> None: + async def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - await self._send_model(message) + await self._send_model(message or ListenV1Finalize(type="Finalize")) - async def send_close_stream(self, message: ListenV1CloseStream) -> None: + async def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - await self._send_model(message) + await self._send_model(message or ListenV1CloseStream(type="CloseStream")) - async def send_keep_alive(self, message: ListenV1KeepAlive) -> None: + async def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - await self._send_model(message) + await self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) async def recv(self) -> V1SocketClientResponse: """ @@ -144,7 +142,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -156,26 +154,26 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_finalize(self, message: ListenV1Finalize) -> None: + def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - self._send_model(message) + self._send_model(message or ListenV1Finalize(type="Finalize")) - def send_close_stream(self, message: ListenV1CloseStream) -> None: + def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - self._send_model(message) + self._send_model(message or ListenV1CloseStream(type="CloseStream")) - def send_keep_alive(self, message: ListenV1KeepAlive) -> None: + def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - self._send_model(message) + self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) def recv(self) -> V1SocketClientResponse: """ diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 72bc94f9..09935ff8 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -2,9 +2,7 @@ import json import typing -from json.decoder import JSONDecodeError -import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -52,7 +50,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -64,12 +62,12 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_close_stream(self, message: ListenV2CloseStream) -> None: + async def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - await self._send_model(message) + await self._send_model(message or ListenV2CloseStream(type="CloseStream")) async def recv(self) -> V2SocketClientResponse: """ @@ -127,7 +125,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -139,12 +137,12 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_close_stream(self, message: ListenV2CloseStream) -> None: + def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - self._send_model(message) + self._send_model(message or ListenV2CloseStream(type="CloseStream")) def recv(self) -> V2SocketClientResponse: """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index cac0ae3c..e04280bf 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -2,9 +2,7 @@ import json import typing -from json.decoder import JSONDecodeError -import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -56,7 +54,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -68,26 +66,26 @@ async def send_text(self, message: SpeakV1Text) -> None: """ await self._send_model(message) - async def send_flush(self, message: SpeakV1Flush) -> None: + async def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Flush(type="Flush")) - async def send_clear(self, message: SpeakV1Clear) -> None: + async def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Clear(type="Clear")) - async def send_close(self, message: SpeakV1Close) -> None: + async def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Close(type="Close")) async def recv(self) -> V1SocketClientResponse: """ @@ -145,7 +143,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -157,26 +155,26 @@ def send_text(self, message: SpeakV1Text) -> None: """ self._send_model(message) - def send_flush(self, message: SpeakV1Flush) -> None: + def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - self._send_model(message) + self._send_model(message or SpeakV1Flush(type="Flush")) - def send_clear(self, message: SpeakV1Clear) -> None: + def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - self._send_model(message) + self._send_model(message or SpeakV1Clear(type="Clear")) - def send_close(self, message: SpeakV1Close) -> None: + def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - self._send_model(message) + self._send_model(message or SpeakV1Close(type="Close")) def recv(self) -> V1SocketClientResponse: """ diff --git a/tests/custom/test_text_builder.py b/tests/custom/test_text_builder.py new file mode 100644 index 00000000..77a7ed1b --- /dev/null +++ b/tests/custom/test_text_builder.py @@ -0,0 +1,500 @@ +""" +Tests for TextBuilder and TTS helper utilities +""" + +import pytest +from deepgram.helpers import ( + TextBuilder, + add_pronunciation, + ssml_to_deepgram, + validate_ipa, + validate_pause, +) + + +class TestTextBuilder: + """Tests for the TextBuilder class""" + + def test_basic_text(self): + """Test adding plain text""" + builder = TextBuilder() + result = builder.text("Hello world").build() + assert result == "Hello world" + + def test_multiple_text_parts(self): + """Test chaining multiple text parts""" + builder = TextBuilder() + result = builder.text("Hello ").text("world").build() + assert result == "Hello world" + + def test_pronunciation(self): + """Test adding pronunciation""" + builder = TextBuilder() + result = builder.pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn").build() + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + + def test_text_with_pronunciation(self): + """Test mixing text and pronunciation""" + builder = TextBuilder() + result = ( + builder + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily") + .build() + ) + assert "Take " in result + assert '"word": "azathioprine"' in result + assert " twice daily" in result + + def test_pause(self): + """Test adding pause""" + builder = TextBuilder() + result = builder.pause(500).build() + assert result == "{pause:500}" + + def test_text_with_pause(self): + """Test mixing text and pause""" + builder = TextBuilder() + result = ( + builder + .text("Hello") + .pause(1000) + .text("world") + .build() + ) + assert result == "Hello{pause:1000}world" + + def test_complex_chain(self): + """Test complex chaining with all features""" + builder = TextBuilder() + result = ( + builder + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily with ") + .pronunciation("dupilumab", "duːˈpɪljuːmæb") + .text(" injections") + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + assert "Take " in result + assert '"word": "azathioprine"' in result + assert " twice daily with " in result + assert '"word": "dupilumab"' in result + assert " injections" in result + assert "{pause:500}" in result + assert " Do not exceed prescribed dosage." in result + + def test_pronunciation_limit(self): + """Test pronunciation count limit (500 max)""" + builder = TextBuilder() + + # Add 500 pronunciations (should work) + for i in range(500): + builder.pronunciation(f"word{i}", "test") + + # 501st should raise error + with pytest.raises(ValueError, match="Maximum 500 pronunciations"): + builder.pronunciation("extra", "test") + + def test_pause_limit(self): + """Test pause count limit (50 max)""" + builder = TextBuilder() + + # Add 50 pauses (should work) + for i in range(50): + builder.pause(500) + + # 51st should raise error + with pytest.raises(ValueError, match="Maximum 50 pauses"): + builder.pause(500) + + def test_character_limit(self): + """Test character count validation (2000 max)""" + builder = TextBuilder() + + # Add text approaching the limit + builder.text("x" * 2000) + + # Should work at exactly 2000 + result = builder.build() + assert len(result) == 2000 + + # Exceeding should raise error + builder2 = TextBuilder() + builder2.text("x" * 2001) + with pytest.raises(ValueError, match="exceeds 2000 character limit"): + builder2.build() + + def test_empty_builder(self): + """Test building with no content""" + builder = TextBuilder() + result = builder.build() + assert result == "" + + def test_invalid_ipa(self): + """Test validation of IPA pronunciation""" + builder = TextBuilder() + + # Should reject IPA with invalid characters + with pytest.raises(ValueError, match="invalid character"): + builder.pronunciation("word", 'invalid"quote') + + with pytest.raises(ValueError, match="invalid character"): + builder.pronunciation("word", "invalid\nline") + + def test_invalid_pause_duration(self): + """Test pause duration validation""" + builder = TextBuilder() + + # Too short + with pytest.raises(ValueError, match="at least 500ms"): + builder.pause(400) + + # Too long + with pytest.raises(ValueError, match="not exceed 5000ms"): + builder.pause(5001) + + # Not in 100ms increments + with pytest.raises(ValueError, match="100ms increments"): + builder.pause(550) + + def test_pause_boundary_values(self): + """Test pause at valid boundaries""" + builder = TextBuilder() + + # Minimum valid + result1 = builder.pause(500).build() + assert "{pause:500}" in result1 + + # Maximum valid + builder2 = TextBuilder() + result2 = builder2.pause(5000).build() + assert "{pause:5000}" in result2 + + +class TestAddPronunciation: + """Tests for the add_pronunciation function""" + + def test_basic_replacement(self): + """Test basic word replacement""" + text = "Take azathioprine twice daily." + result = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + assert "Take " in result + assert " twice daily." in result + + def test_multiple_replacements(self): + """Test replacing multiple words""" + text = "Take azathioprine twice daily with dupilumab injections." + text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") + + assert '"word": "azathioprine"' in text + assert '"word": "dupilumab"' in text + + def test_whole_word_only(self): + """Test that replacement only affects whole words""" + text = "The therapist prescribed therapy." + result = add_pronunciation(text, "The", "ðiː") + + # Should only replace "The", not "the" in "therapist" or "therapy" + assert result.count('"word"') == 1 + assert "therapist" in result + assert "therapy" in result + + def test_case_sensitive(self): + """Test that replacement is case-sensitive""" + text = "Take azathioprine. AZATHIOPRINE is different." + result = add_pronunciation(text, "azathioprine", "test") + + # Should only replace lowercase version (first occurrence) + assert result.count('"word"') == 1 + assert "AZATHIOPRINE" in result + + def test_word_not_found(self): + """Test replacement when word is not in text""" + text = "Hello world" + result = add_pronunciation(text, "missing", "test") + + # Text should be unchanged + assert result == text + + +class TestSsmlToDeepgram: + """Tests for SSML conversion""" + + def test_basic_phoneme(self): + """Test converting basic phoneme tag""" + ssml = 'azathioprine' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in result + + def test_basic_break(self): + """Test converting break tag (milliseconds)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + assert result == "{pause:500}" + + def test_break_seconds(self): + """Test converting break tag (seconds)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + assert result == "{pause:500}" + + def test_speak_wrapper(self): + """Test handling wrapper tag""" + ssml = 'Hello world' + result = ssml_to_deepgram(ssml) + + assert result == "Hello world" + + def test_complex_ssml(self): + """Test complex SSML with multiple elements""" + ssml = ''' + Take azathioprine + Do not exceed dosage. + ''' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert "{pause:500}" in result + assert "Do not exceed dosage." in result + + def test_multiple_phonemes(self): + """Test multiple phoneme tags""" + ssml = '''Take azathioprine + with dupilumab''' + result = ssml_to_deepgram(ssml) + + assert '"word": "azathioprine"' in result + assert '"word": "dupilumab"' in result + + def test_plain_text(self): + """Test plain text without SSML tags""" + text = "Hello world" + result = ssml_to_deepgram(text) + + assert result == text + + def test_break_out_of_range(self): + """Test break with out-of-range duration (should round to valid)""" + ssml = '' + result = ssml_to_deepgram(ssml) + + # Should round to nearest valid value (500ms) + assert "{pause:" in result + + +class TestFromSsml: + """Tests for TextBuilder.from_ssml() method""" + + def test_from_ssml_basic(self): + """Test parsing SSML into builder""" + ssml = 'Hello world' + builder = TextBuilder() + result = builder.from_ssml(ssml).build() + + assert "Hello world" in result + + def test_from_ssml_with_additional_text(self): + """Test mixing SSML parsing with additional builder methods""" + ssml = 'Take medicine' + builder = TextBuilder() + result = ( + builder + .from_ssml(ssml) + .pause(500) + .text(" Do not exceed dosage.") + .build() + ) + + assert '"word": "medicine"' in result + assert "{pause:500}" in result + assert "Do not exceed dosage." in result + + def test_from_ssml_counts_pronunciations(self): + """Test that from_ssml updates internal counters""" + # Create SSML with pronunciations + pronunciations = ''.join([ + f'word{i} ' + for i in range(500) + ]) + ssml = f'{pronunciations}' + + builder = TextBuilder() + builder.from_ssml(ssml) + + # Should hit the limit + with pytest.raises(ValueError, match="Maximum 500 pronunciations"): + builder.pronunciation("extra", "test") + + +class TestValidateIpa: + """Tests for IPA validation""" + + def test_valid_ipa(self): + """Test valid IPA strings""" + is_valid, msg = validate_ipa("ˌæzəˈθaɪəpriːn") + assert is_valid is True + assert msg == "" + + def test_empty_ipa(self): + """Test empty IPA string""" + is_valid, msg = validate_ipa("") + assert is_valid is False + assert "cannot be empty" in msg + + def test_invalid_characters(self): + """Test IPA with invalid characters""" + # Double quote + is_valid, msg = validate_ipa('test"quote') + assert is_valid is False + assert "invalid character" in msg + + # Newline + is_valid, msg = validate_ipa("test\nline") + assert is_valid is False + assert "invalid character" in msg + + def test_too_long(self): + """Test IPA exceeding length limit""" + is_valid, msg = validate_ipa("x" * 101) + assert is_valid is False + assert "exceeds 100 character limit" in msg + + def test_not_string(self): + """Test non-string IPA""" + is_valid, msg = validate_ipa(123) + assert is_valid is False + assert "must be a string" in msg + + +class TestValidatePause: + """Tests for pause validation""" + + def test_valid_pauses(self): + """Test valid pause durations""" + # Minimum + is_valid, msg = validate_pause(500) + assert is_valid is True + + # Maximum + is_valid, msg = validate_pause(5000) + assert is_valid is True + + # Mid-range + is_valid, msg = validate_pause(2500) + assert is_valid is True + + def test_too_short(self): + """Test pause below minimum""" + is_valid, msg = validate_pause(400) + assert is_valid is False + assert "at least 500ms" in msg + + def test_too_long(self): + """Test pause above maximum""" + is_valid, msg = validate_pause(5001) + assert is_valid is False + assert "not exceed 5000ms" in msg + + def test_invalid_increment(self): + """Test pause not in 100ms increments""" + is_valid, msg = validate_pause(550) + assert is_valid is False + assert "100ms increments" in msg + + def test_not_integer(self): + """Test non-integer pause""" + is_valid, msg = validate_pause(500.5) + assert is_valid is False + assert "must be an integer" in msg + + +class TestIntegration: + """Integration tests combining multiple features""" + + def test_medical_example(self): + """Test the medical prescription example from the spec""" + text = ( + TextBuilder() + .text("Take ") + .pronunciation("azathioprine", "ˌæzəˈθaɪəpriːn") + .text(" twice daily with ") + .pronunciation("dupilumab", "duːˈpɪljuːmæb") + .text(" injections") + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + # Verify all components are present + assert "Take " in text + assert '"word": "azathioprine"' in text + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text + assert " twice daily with " in text + assert '"word": "dupilumab"' in text + assert '"pronounce": "duːˈpɪljuːmæb"' in text + assert " injections" in text + assert "{pause:500}" in text + assert " Do not exceed prescribed dosage." in text + + def test_ssml_migration(self): + """Test SSML to Deepgram migration workflow""" + ssml = ''' + Take azathioprine + Do not exceed dosage. + ''' + + # Method 1: Direct conversion + text1 = ssml_to_deepgram(ssml) + + # Method 2: Using builder + text2 = TextBuilder().from_ssml(ssml).build() + + # Both should produce similar results + assert '"word": "azathioprine"' in text1 + assert "{pause:500}" in text1 + assert '"word": "azathioprine"' in text2 + assert "{pause:500}" in text2 + + def test_builder_with_ssml_and_additions(self): + """Test the mixed usage example from the spec""" + some_imported_ssml = ''' + Take medicine + ''' + + text = ( + TextBuilder() + .from_ssml(some_imported_ssml) + .pause(500) + .text(" Do not exceed prescribed dosage.") + .build() + ) + + assert '"word": "medicine"' in text + assert "{pause:500}" in text + assert " Do not exceed prescribed dosage." in text + + def test_standalone_function_workflow(self): + """Test using standalone add_pronunciation function""" + text = "Take azathioprine twice daily with dupilumab injections." + text = add_pronunciation(text, "azathioprine", "ˌæzəˈθaɪəpriːn") + text = add_pronunciation(text, "dupilumab", "duːˈpɪljuːmæb") + + assert '"word": "azathioprine"' in text + assert '"pronounce": "ˌæzəˈθaɪəpriːn"' in text + assert '"word": "dupilumab"' in text + assert '"pronounce": "duːˈpɪljuːmæb"' in text + diff --git a/tests/custom/test_transport.py b/tests/custom/test_transport.py new file mode 100644 index 00000000..ba860fa5 --- /dev/null +++ b/tests/custom/test_transport.py @@ -0,0 +1,481 @@ +"""Tests for custom WebSocket transport support.""" + +import json +import sys +from typing import Any, Dict, Iterator, List +from unittest.mock import MagicMock + +import pytest + +from deepgram.transport import ( + AsyncTransport, + SyncTransport, + _AsyncTransportShim, + _SyncTransportShim, + _TARGET_MODULES, + install_transport, + restore_transport, +) + + +# --------------------------------------------------------------------------- +# Mock transport implementations +# --------------------------------------------------------------------------- + +class MockSyncTransport: + """Minimal sync transport that satisfies the SyncTransport protocol.""" + + def __init__(self, messages: List[str] = None): + self._messages = list(messages or []) + self._sent: List[Any] = [] + self._closed = False + + def send(self, data: Any) -> None: + self._sent.append(data) + + def recv(self) -> str: + if self._messages: + return self._messages.pop(0) + raise StopIteration + + def __iter__(self) -> Iterator: + return iter(self._messages) + + def close(self) -> None: + self._closed = True + + +class MockAsyncTransport: + """Minimal async transport that satisfies the AsyncTransport protocol.""" + + def __init__(self, messages: List[str] = None): + self._messages = list(messages or []) + self._sent: List[Any] = [] + self._closed = False + + async def send(self, data: Any) -> None: + self._sent.append(data) + + async def recv(self) -> str: + if self._messages: + return self._messages.pop(0) + raise StopAsyncIteration + + async def __aiter__(self): + for msg in self._messages: + yield msg + + async def close(self) -> None: + self._closed = True + + +# --------------------------------------------------------------------------- +# Fixtures +# --------------------------------------------------------------------------- + +@pytest.fixture(autouse=True) +def _restore_after_test(): + """Ensure transport patches are cleaned up after every test.""" + yield + restore_transport() + + +# --------------------------------------------------------------------------- +# Protocol conformance +# --------------------------------------------------------------------------- + +class TestProtocolConformance: + def test_sync_transport_protocol(self): + transport = MockSyncTransport() + assert isinstance(transport, SyncTransport) + + def test_async_transport_protocol(self): + transport = MockAsyncTransport() + assert isinstance(transport, AsyncTransport) + + def test_object_not_conforming_sync(self): + assert not isinstance(object(), SyncTransport) + + def test_object_not_conforming_async(self): + assert not isinstance(object(), AsyncTransport) + + +# --------------------------------------------------------------------------- +# Sync shim +# --------------------------------------------------------------------------- + +class TestSyncTransportShim: + def test_connect_calls_factory(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com", additional_headers={"Authorization": "token xyz"}) as t: + assert t is transport + + factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) + + def test_connect_closes_transport(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com"): + assert not transport._closed + + assert transport._closed + + def test_connect_default_headers(self): + transport = MockSyncTransport() + factory = MagicMock(return_value=transport) + shim = _SyncTransportShim(factory) + + with shim.connect("wss://example.com"): + pass + + factory.assert_called_once_with("wss://example.com", {}) + + +# --------------------------------------------------------------------------- +# Async shim +# --------------------------------------------------------------------------- + +class TestAsyncTransportShim: + async def test_connect_calls_factory(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com", extra_headers={"Authorization": "token xyz"}) as t: + assert t is transport + + factory.assert_called_once_with("wss://example.com", {"Authorization": "token xyz"}) + + async def test_connect_closes_transport(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com"): + assert not transport._closed + + assert transport._closed + + async def test_connect_default_headers(self): + transport = MockAsyncTransport() + factory = MagicMock(return_value=transport) + shim = _AsyncTransportShim(factory) + + async with shim("wss://example.com"): + pass + + factory.assert_called_once_with("wss://example.com", {}) + + +# --------------------------------------------------------------------------- +# install_transport / restore_transport +# --------------------------------------------------------------------------- + +def _ensure_modules_loaded(): + """Force-import all target modules so they appear in sys.modules.""" + for mod_path in _TARGET_MODULES: + if mod_path not in sys.modules: + __import__(mod_path) + + +class TestInstallRestore: + def test_install_sync_patches_all_modules(self): + _ensure_modules_loaded() + + factory = MagicMock() + install_transport(sync_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert isinstance(mod.websockets_sync_client, _SyncTransportShim), ( + f"{mod_path}.websockets_sync_client was not patched" + ) + + def test_install_async_patches_all_modules(self): + _ensure_modules_loaded() + + factory = MagicMock() + install_transport(async_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_client_connect"): + assert isinstance(mod.websockets_client_connect, _AsyncTransportShim), ( + f"{mod_path}.websockets_client_connect was not patched" + ) + + def test_restore_undoes_patches(self): + _ensure_modules_loaded() + + # Capture originals + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = { + "sync": getattr(mod, "websockets_sync_client", None), + "async": getattr(mod, "websockets_client_connect", None), + } + + install_transport(sync_factory=MagicMock(), async_factory=MagicMock()) + restore_transport() + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path]["sync"] is not None: + assert mod.websockets_sync_client is originals[mod_path]["sync"], ( + f"{mod_path}.websockets_sync_client was not restored" + ) + if originals[mod_path]["async"] is not None: + assert mod.websockets_client_connect is originals[mod_path]["async"], ( + f"{mod_path}.websockets_client_connect was not restored" + ) + + def test_install_only_sync_leaves_async_untouched(self): + _ensure_modules_loaded() + + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = getattr(mod, "websockets_client_connect", None) + + install_transport(sync_factory=MagicMock()) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path] is not None: + assert mod.websockets_client_connect is originals[mod_path] + + def test_install_only_async_leaves_sync_untouched(self): + _ensure_modules_loaded() + + originals = {} + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + originals[mod_path] = getattr(mod, "websockets_sync_client", None) + + install_transport(async_factory=MagicMock()) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if originals[mod_path] is not None: + assert mod.websockets_sync_client is originals[mod_path] + + +# --------------------------------------------------------------------------- +# Conflict guard +# --------------------------------------------------------------------------- + +class TestConflictGuard: + def test_same_sync_factory_is_idempotent(self): + _ensure_modules_loaded() + factory = MagicMock() + install_transport(sync_factory=factory) + install_transport(sync_factory=factory) # should not raise + + def test_same_async_factory_is_idempotent(self): + _ensure_modules_loaded() + factory = MagicMock() + install_transport(async_factory=factory) + install_transport(async_factory=factory) # should not raise + + def test_different_sync_factory_raises(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + with pytest.raises(RuntimeError, match="different sync transport factory"): + install_transport(sync_factory=MagicMock()) + + def test_different_async_factory_raises(self): + _ensure_modules_loaded() + install_transport(async_factory=MagicMock()) + with pytest.raises(RuntimeError, match="different async transport factory"): + install_transport(async_factory=MagicMock()) + + def test_restore_then_reinstall_different_factory(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + restore_transport() + install_transport(sync_factory=MagicMock()) # should not raise + + def test_sync_and_async_factories_are_independent(self): + _ensure_modules_loaded() + install_transport(sync_factory=MagicMock()) + install_transport(async_factory=MagicMock()) # should not raise + + +# --------------------------------------------------------------------------- +# End-to-end: sync listen with mock transport +# --------------------------------------------------------------------------- + +def _valid_metadata_json() -> str: + """Return a JSON string that matches the ListenV1Metadata Pydantic model.""" + return json.dumps({ + "type": "Metadata", + "transaction_key": "test-txn-key", + "request_id": "req-001", + "sha256": "abc123", + "created": "2024-01-01T00:00:00Z", + "duration": 1.5, + "channels": 1, + }) + + +class TestSyncEndToEnd: + def test_listen_v1_with_mock_transport(self): + """Verify a mock transport receives messages through the event system.""" + from deepgram.core.events import EventEmitterMixin, EventType + from deepgram.listen.v1.socket_client import V1SocketClient + + transcript_json = _valid_metadata_json() + + transport = MockSyncTransport(messages=[transcript_json]) + client = V1SocketClient(websocket=transport) + + received = [] + errors = [] + client.on(EventType.MESSAGE, lambda msg: received.append(msg)) + client.on(EventType.ERROR, lambda err: errors.append(err)) + + client.start_listening() + + assert len(errors) == 0 + assert len(received) == 1 + + def test_custom_transport_error_emits_error_event(self): + """When the transport raises, EventType.ERROR should fire.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import V1SocketClient + + class FailingTransport: + def send(self, data): pass + def recv(self): raise ConnectionError("boom") + def close(self): pass + def __iter__(self): + raise ConnectionError("boom") + + client = V1SocketClient(websocket=FailingTransport()) + + errors = [] + closed = [] + client.on(EventType.ERROR, lambda err: errors.append(err)) + client.on(EventType.CLOSE, lambda _: closed.append(True)) + + client.start_listening() + + assert len(errors) == 1 + assert isinstance(errors[0], ConnectionError) + assert len(closed) == 1 + + +# --------------------------------------------------------------------------- +# End-to-end: async listen with mock transport +# --------------------------------------------------------------------------- + +class TestAsyncEndToEnd: + async def test_listen_v1_async_with_mock_transport(self): + """Verify a mock async transport works through the event system.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import AsyncV1SocketClient + + transcript_json = _valid_metadata_json() + + class AsyncMockWS: + def __init__(self): + self._messages = [transcript_json] + + async def send(self, data): pass + async def recv(self): return self._messages.pop(0) + async def close(self): pass + + async def __aiter__(self): + for msg in list(self._messages): + yield msg + + transport = AsyncMockWS() + client = AsyncV1SocketClient(websocket=transport) + + received = [] + errors = [] + client.on(EventType.MESSAGE, lambda msg: received.append(msg)) + client.on(EventType.ERROR, lambda err: errors.append(err)) + + await client.start_listening() + + assert len(errors) == 0 + assert len(received) == 1 + + async def test_async_transport_error_emits_error_event(self): + """When the async transport raises, EventType.ERROR should fire.""" + from deepgram.core.events import EventType + from deepgram.listen.v1.socket_client import AsyncV1SocketClient + + class FailingAsyncTransport: + async def send(self, data): pass + async def recv(self): raise ConnectionError("async boom") + async def close(self): pass + + async def __aiter__(self): + raise ConnectionError("async boom") + yield # unreachable — makes this an async generator + + client = AsyncV1SocketClient(websocket=FailingAsyncTransport()) + + errors = [] + closed = [] + client.on(EventType.ERROR, lambda err: errors.append(err)) + client.on(EventType.CLOSE, lambda _: closed.append(True)) + + await client.start_listening() + + assert len(errors) == 1 + assert isinstance(errors[0], ConnectionError) + assert len(closed) == 1 + + +# --------------------------------------------------------------------------- +# DeepgramClient construction triggers patching +# --------------------------------------------------------------------------- + +class TestClientConstruction: + def test_deepgram_client_installs_sync_transport(self): + _ensure_modules_loaded() + + factory = MagicMock() + from deepgram.client import DeepgramClient + DeepgramClient(api_key="test-key", transport_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert isinstance(mod.websockets_sync_client, _SyncTransportShim) + + def test_deepgram_client_without_factory_does_not_patch(self): + _ensure_modules_loaded() + + # Ensure clean state + restore_transport() + + from deepgram.client import DeepgramClient + DeepgramClient(api_key="test-key") + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_sync_client"): + assert not isinstance(mod.websockets_sync_client, _SyncTransportShim) + + def test_async_deepgram_client_installs_async_transport(self): + _ensure_modules_loaded() + + factory = MagicMock() + from deepgram.client import AsyncDeepgramClient + AsyncDeepgramClient(api_key="test-key", transport_factory=factory) + + for mod_path in _TARGET_MODULES: + mod = sys.modules[mod_path] + if hasattr(mod, "websockets_client_connect"): + assert isinstance(mod.websockets_client_connect, _AsyncTransportShim) From 4276cfbbebfd91303e76fc12af53897263cd62cd Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 12:40:13 +0000 Subject: [PATCH 05/11] fix(fernignore): protect hand-written test files from regen --- .fernignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.fernignore b/.fernignore index 796e20de..b49c90f6 100644 --- a/.fernignore +++ b/.fernignore @@ -20,6 +20,10 @@ tests/wire/test_listen_v1_media.py # src/deepgram/listen/v2/socket_client.py # src/deepgram/agent/v1/socket_client.py +# Hand-written custom tests +tests/custom/test_text_builder.py +tests/custom/test_transport.py + # Manual standalone tests tests/manual From 20f34ad8ee8c6a64a02bd3888a253fb47a409025 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:41:32 +0000 Subject: [PATCH 06/11] SDK regeneration --- .fern/metadata.json | 2 +- src/deepgram/agent/v1/socket_client.py | 38 +++++++------------------ src/deepgram/core/client_wrapper.py | 1 + src/deepgram/listen/v1/socket_client.py | 30 ++++++++++--------- src/deepgram/listen/v2/socket_client.py | 14 +++++---- src/deepgram/speak/v1/socket_client.py | 30 ++++++++++--------- 6 files changed, 52 insertions(+), 63 deletions(-) diff --git a/.fern/metadata.json b/.fern/metadata.json index 8eb0bbad..c9ecd919 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -16,5 +16,5 @@ "skip_validation": true } }, - "sdkVersion": "0.0.333" + "sdkVersion": "6.0.1" } \ No newline at end of file diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index 56dd49fe..53428363 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -33,26 +35,6 @@ except ImportError: from websockets import WebSocketClientProtocol # type: ignore -def _sanitize_numeric_types(obj: typing.Any) -> typing.Any: - """ - Recursively convert float values that are whole numbers to int. - - Workaround for Fern-generated models that type integer API fields - (like sample_rate) as float, causing JSON serialization to produce - values like 44100.0 instead of 44100. The Deepgram API rejects - float representations of integer fields. - - See: https://github.com/deepgram/internal-api-specs/issues/205 - """ - if isinstance(obj, dict): - return {k: _sanitize_numeric_types(v) for k, v in obj.items()} - elif isinstance(obj, list): - return [_sanitize_numeric_types(item) for item in obj] - elif isinstance(obj, float) and obj.is_integer(): - return int(obj) - return obj - - V1SocketClientResponse = typing.Union[ AgentV1ReceiveFunctionCallResponse, AgentV1PromptUpdated, @@ -103,7 +85,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -143,12 +125,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp """ await self._send_model(message) - async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: + async def send_keep_alive(self, message: AgentV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - await self._send_model(message or AgentV1KeepAlive()) + await self._send_model(message) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -186,7 +168,7 @@ async def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - await self._send(_sanitize_numeric_types(data.dict())) + await self._send(data.dict()) class V1SocketClient(EventEmitterMixin): @@ -220,7 +202,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -260,12 +242,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) """ self._send_model(message) - def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: + def send_keep_alive(self, message: AgentV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - self._send_model(message or AgentV1KeepAlive()) + self._send_model(message) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -303,4 +285,4 @@ def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - self._send(_sanitize_numeric_types(data.dict())) + self._send(data.dict()) diff --git a/src/deepgram/core/client_wrapper.py b/src/deepgram/core/client_wrapper.py index 18b04517..33b53ce1 100644 --- a/src/deepgram/core/client_wrapper.py +++ b/src/deepgram/core/client_wrapper.py @@ -25,6 +25,7 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { + "User-Agent": "deepgram-sdk/6.0.1", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index ce948284..1c186616 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -53,7 +55,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -65,26 +67,26 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: + async def send_finalize(self, message: ListenV1Finalize) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - await self._send_model(message or ListenV1Finalize(type="Finalize")) + await self._send_model(message) - async def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: + async def send_close_stream(self, message: ListenV1CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - await self._send_model(message or ListenV1CloseStream(type="CloseStream")) + await self._send_model(message) - async def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: + async def send_keep_alive(self, message: ListenV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - await self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) + await self._send_model(message) async def recv(self) -> V1SocketClientResponse: """ @@ -142,7 +144,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -154,26 +156,26 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: + def send_finalize(self, message: ListenV1Finalize) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - self._send_model(message or ListenV1Finalize(type="Finalize")) + self._send_model(message) - def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: + def send_close_stream(self, message: ListenV1CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - self._send_model(message or ListenV1CloseStream(type="CloseStream")) + self._send_model(message) - def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: + def send_keep_alive(self, message: ListenV1KeepAlive) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) + self._send_model(message) def recv(self) -> V1SocketClientResponse: """ diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 09935ff8..72bc94f9 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -50,7 +52,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -62,12 +64,12 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: + async def send_close_stream(self, message: ListenV2CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - await self._send_model(message or ListenV2CloseStream(type="CloseStream")) + await self._send_model(message) async def recv(self) -> V2SocketClientResponse: """ @@ -125,7 +127,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -137,12 +139,12 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: + def send_close_stream(self, message: ListenV2CloseStream) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - self._send_model(message or ListenV2CloseStream(type="CloseStream")) + self._send_model(message) def recv(self) -> V2SocketClientResponse: """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index e04280bf..cac0ae3c 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -2,7 +2,9 @@ import json import typing +from json.decoder import JSONDecodeError +import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType from ...core.pydantic_utilities import parse_obj_as @@ -54,7 +56,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -66,26 +68,26 @@ async def send_text(self, message: SpeakV1Text) -> None: """ await self._send_model(message) - async def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: + async def send_flush(self, message: SpeakV1Flush) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - await self._send_model(message or SpeakV1Flush(type="Flush")) + await self._send_model(message) - async def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: + async def send_clear(self, message: SpeakV1Clear) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - await self._send_model(message or SpeakV1Clear(type="Clear")) + await self._send_model(message) - async def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: + async def send_close(self, message: SpeakV1Close) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - await self._send_model(message or SpeakV1Close(type="Close")) + await self._send_model(message) async def recv(self) -> V1SocketClientResponse: """ @@ -143,7 +145,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except Exception as exc: + except (websockets.WebSocketException, JSONDecodeError) as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) @@ -155,26 +157,26 @@ def send_text(self, message: SpeakV1Text) -> None: """ self._send_model(message) - def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: + def send_flush(self, message: SpeakV1Flush) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - self._send_model(message or SpeakV1Flush(type="Flush")) + self._send_model(message) - def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: + def send_clear(self, message: SpeakV1Clear) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - self._send_model(message or SpeakV1Clear(type="Clear")) + self._send_model(message) - def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: + def send_close(self, message: SpeakV1Close) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - self._send_model(message or SpeakV1Close(type="Close")) + self._send_model(message) def recv(self) -> V1SocketClientResponse: """ From cb6ad8aca1c553e4a7f89578e546b7c595bebe81 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 12:55:11 +0000 Subject: [PATCH 07/11] fix(websockets): widen exception handling to support custom transports Catch Exception instead of (WebSocketException, JSONDecodeError) in start_listening so non-websocket transports can emit errors properly. --- src/deepgram/agent/v1/socket_client.py | 4 ++-- src/deepgram/listen/v1/socket_client.py | 4 ++-- src/deepgram/listen/v2/socket_client.py | 4 ++-- src/deepgram/speak/v1/socket_client.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index 53428363..fefc0ee6 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -85,7 +85,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -202,7 +202,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index 1c186616..07e92ad4 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -55,7 +55,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -144,7 +144,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 72bc94f9..f3c80fd7 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -52,7 +52,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -127,7 +127,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index cac0ae3c..980c8220 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -56,7 +56,7 @@ async def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: await self._emit_async(EventType.ERROR, exc) finally: await self._emit_async(EventType.CLOSE, None) @@ -145,7 +145,7 @@ def start_listening(self): json_data = json.loads(raw_message) parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) - except (websockets.WebSocketException, JSONDecodeError) as exc: + except Exception as exc: self._emit(EventType.ERROR, exc) finally: self._emit(EventType.CLOSE, None) From 273792321bb8f1e58a7dca19d480bd3dddf50504 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 13:04:23 +0000 Subject: [PATCH 08/11] fix(websockets): switch socket clients to construct_type for unknown message tolerance Replace parse_obj_as with construct_type in all socket clients so unknown message types are silently coerced instead of raising ValidationError. Also fix v2 listen example to actually send audio. --- .../14-transcription-live-websocket-v2.py | 55 +++++++++++++------ src/deepgram/agent/v1/socket_client.py | 14 ++--- src/deepgram/listen/v1/socket_client.py | 14 ++--- src/deepgram/listen/v2/socket_client.py | 14 ++--- src/deepgram/speak/v1/socket_client.py | 14 ++--- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/examples/14-transcription-live-websocket-v2.py b/examples/14-transcription-live-websocket-v2.py index ef86e07a..57e91b18 100644 --- a/examples/14-transcription-live-websocket-v2.py +++ b/examples/14-transcription-live-websocket-v2.py @@ -5,6 +5,10 @@ with contextual turn detection. """ +import os +import threading +import time +from pathlib import Path from typing import Union from dotenv import load_dotenv @@ -14,6 +18,7 @@ from deepgram import DeepgramClient from deepgram.core.events import EventType from deepgram.listen.v2.types import ( + ListenV2CloseStream, ListenV2Connected, ListenV2FatalError, ListenV2TurnInfo, @@ -21,35 +26,51 @@ ListenV2SocketClientResponse = Union[ListenV2Connected, ListenV2TurnInfo, ListenV2FatalError] -client = DeepgramClient() +client = DeepgramClient(api_key=os.environ.get("DEEPGRAM_API_KEY")) try: - with client.listen.v2.connect(model="flux-general-en", encoding="linear16", sample_rate=16000) as connection: + with client.listen.v2.connect( + model="flux-general-en", + encoding="linear16", + sample_rate="16000", + ) as connection: def on_message(message: ListenV2SocketClientResponse) -> None: - msg_type = getattr(message, "type", "Unknown") - print(f"Received {msg_type} event") + msg_type = getattr(message, "type", type(message).__name__) + print(f"Received {msg_type} event ({type(message).__name__})") # Extract transcription from TurnInfo events if isinstance(message, ListenV2TurnInfo): - print(f"Turn transcript: {message.transcript}") - print(f"Turn event: {message.event}") - print(f"Turn index: {message.turn_index}") + print(f" transcript: {message.transcript}") + print(f" event: {message.event}") + print(f" turn_index: {message.turn_index}") connection.on(EventType.OPEN, lambda _: print("Connection opened")) connection.on(EventType.MESSAGE, on_message) connection.on(EventType.CLOSE, lambda _: print("Connection closed")) - connection.on(EventType.ERROR, lambda error: print(f"Error: {error}")) + connection.on(EventType.ERROR, lambda error: print(f"Error: {type(error).__name__}: {error}")) - # Start listening - this blocks until the connection closes - # In production, you would send audio data here using connection.send_media() - connection.start_listening() + # Send audio in a background thread so start_listening can process responses + def send_audio(): + audio_path = Path(__file__).parent / "fixtures" / "audio.wav" + with open(audio_path, "rb") as f: + audio = f.read() + + # Send in chunks + chunk_size = 4096 + for i in range(0, len(audio), chunk_size): + connection.send_media(audio[i : i + chunk_size]) + time.sleep(0.01) # pace the sending + + # Signal end of audio + time.sleep(2) + connection.send_close_stream(ListenV2CloseStream(type="CloseStream")) - # For async version: - # from deepgram import AsyncDeepgramClient - # async with client.listen.v2.connect(...) as connection: - # # ... same event handlers ... - # await connection.start_listening() + sender = threading.Thread(target=send_audio, daemon=True) + sender.start() + + # This blocks until the connection closes + connection.start_listening() except Exception as e: - print(f"Error: {e}") + print(f"Error: {type(e).__name__}: {e}") diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index fefc0ee6..ab9bc46b 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -7,7 +7,7 @@ import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType -from ...core.pydantic_utilities import parse_obj_as +from ...core.unchecked_base_model import construct_type from .types.agent_v1agent_audio_done import AgentV1AgentAudioDone from .types.agent_v1agent_started_speaking import AgentV1AgentStartedSpeaking from .types.agent_v1agent_thinking import AgentV1AgentThinking @@ -64,7 +64,7 @@ async def __aiter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore async def start_listening(self): """ @@ -83,7 +83,7 @@ async def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) except Exception as exc: await self._emit_async(EventType.ERROR, exc) @@ -154,7 +154,7 @@ async def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore async def _send(self, data: typing.Any) -> None: """ @@ -181,7 +181,7 @@ def __iter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore def start_listening(self): """ @@ -200,7 +200,7 @@ def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) except Exception as exc: self._emit(EventType.ERROR, exc) @@ -271,7 +271,7 @@ def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore def _send(self, data: typing.Any) -> None: """ diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index 07e92ad4..68aa39bd 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -7,7 +7,7 @@ import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType -from ...core.pydantic_utilities import parse_obj_as +from ...core.unchecked_base_model import construct_type from .types.listen_v1close_stream import ListenV1CloseStream from .types.listen_v1finalize import ListenV1Finalize from .types.listen_v1keep_alive import ListenV1KeepAlive @@ -34,7 +34,7 @@ async def __aiter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore async def start_listening(self): """ @@ -53,7 +53,7 @@ async def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) except Exception as exc: await self._emit_async(EventType.ERROR, exc) @@ -96,7 +96,7 @@ async def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore async def _send(self, data: typing.Any) -> None: """ @@ -123,7 +123,7 @@ def __iter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore def start_listening(self): """ @@ -142,7 +142,7 @@ def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) except Exception as exc: self._emit(EventType.ERROR, exc) @@ -185,7 +185,7 @@ def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore def _send(self, data: typing.Any) -> None: """ diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index f3c80fd7..293d5c05 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -7,7 +7,7 @@ import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType -from ...core.pydantic_utilities import parse_obj_as +from ...core.unchecked_base_model import construct_type from .types.listen_v2close_stream import ListenV2CloseStream from .types.listen_v2connected import ListenV2Connected from .types.listen_v2fatal_error import ListenV2FatalError @@ -31,7 +31,7 @@ async def __aiter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V2SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore async def start_listening(self): """ @@ -50,7 +50,7 @@ async def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) except Exception as exc: await self._emit_async(EventType.ERROR, exc) @@ -79,7 +79,7 @@ async def recv(self) -> V2SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V2SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore async def _send(self, data: typing.Any) -> None: """ @@ -106,7 +106,7 @@ def __iter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V2SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore def start_listening(self): """ @@ -125,7 +125,7 @@ def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V2SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) except Exception as exc: self._emit(EventType.ERROR, exc) @@ -154,7 +154,7 @@ def recv(self) -> V2SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V2SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore def _send(self, data: typing.Any) -> None: """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index 980c8220..82c1ac99 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -7,7 +7,7 @@ import websockets import websockets.sync.connection as websockets_sync_connection from ...core.events import EventEmitterMixin, EventType -from ...core.pydantic_utilities import parse_obj_as +from ...core.unchecked_base_model import construct_type from .types.speak_v1clear import SpeakV1Clear from .types.speak_v1cleared import SpeakV1Cleared from .types.speak_v1close import SpeakV1Close @@ -35,7 +35,7 @@ async def __aiter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore async def start_listening(self): """ @@ -54,7 +54,7 @@ async def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore await self._emit_async(EventType.MESSAGE, parsed) except Exception as exc: await self._emit_async(EventType.ERROR, exc) @@ -97,7 +97,7 @@ async def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore async def _send(self, data: typing.Any) -> None: """ @@ -124,7 +124,7 @@ def __iter__(self): if isinstance(message, bytes): yield message else: - yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore def start_listening(self): """ @@ -143,7 +143,7 @@ def start_listening(self): parsed = raw_message else: json_data = json.loads(raw_message) - parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore self._emit(EventType.MESSAGE, parsed) except Exception as exc: self._emit(EventType.ERROR, exc) @@ -186,7 +186,7 @@ def recv(self) -> V1SocketClientResponse: if isinstance(data, bytes): return data # type: ignore json_data = json.loads(data) - return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore def _send(self, data: typing.Any) -> None: """ From 3b2c99965ca461c18bf4200ea6dd68b76addb244 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 13:05:21 +0000 Subject: [PATCH 09/11] chore(fernignore): re-lock socket_client.py files from regen --- .fernignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.fernignore b/.fernignore index b49c90f6..175f261b 100644 --- a/.fernignore +++ b/.fernignore @@ -15,10 +15,10 @@ tests/wire/test_listen_v1_media.py # - Optional message parameter defaults for send_flush, send_close, send_clear, # send_finalize, send_close_stream, send_keep_alive # - Removed unused imports (JSONDecodeError, websockets) flagged by ruff F401 -# src/deepgram/speak/v1/socket_client.py -# src/deepgram/listen/v1/socket_client.py -# src/deepgram/listen/v2/socket_client.py -# src/deepgram/agent/v1/socket_client.py +src/deepgram/speak/v1/socket_client.py +src/deepgram/listen/v1/socket_client.py +src/deepgram/listen/v2/socket_client.py +src/deepgram/agent/v1/socket_client.py # Hand-written custom tests tests/custom/test_text_builder.py From a8d15c49fe5214db1e984629017881ec84eb7c24 Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 13:12:35 +0000 Subject: [PATCH 10/11] fix(agent): restore _sanitize_numeric_types removed by Fern regen --- src/deepgram/agent/v1/socket_client.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index ab9bc46b..a5a24f50 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -35,6 +35,26 @@ except ImportError: from websockets import WebSocketClientProtocol # type: ignore +def _sanitize_numeric_types(obj: typing.Any) -> typing.Any: + """ + Recursively convert float values that are whole numbers to int. + + Workaround for Fern-generated models that type integer API fields + (like sample_rate) as float, causing JSON serialization to produce + values like 44100.0 instead of 44100. The Deepgram API rejects + float representations of integer fields. + + See: https://github.com/deepgram/internal-api-specs/issues/205 + """ + if isinstance(obj, dict): + return {k: _sanitize_numeric_types(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [_sanitize_numeric_types(item) for item in obj] + elif isinstance(obj, float) and obj.is_integer(): + return int(obj) + return obj + + V1SocketClientResponse = typing.Union[ AgentV1ReceiveFunctionCallResponse, AgentV1PromptUpdated, @@ -168,7 +188,7 @@ async def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - await self._send(data.dict()) + await self._send(_sanitize_numeric_types(data.dict())) class V1SocketClient(EventEmitterMixin): @@ -285,4 +305,4 @@ def _send_model(self, data: typing.Any) -> None: """ Send a Pydantic model to the websocket connection. """ - self._send(data.dict()) + self._send(_sanitize_numeric_types(data.dict())) From 8cca90d23568cfb1eac04864cbdb7b653dd4290e Mon Sep 17 00:00:00 2001 From: Luke Oliff Date: Tue, 24 Feb 2026 13:40:17 +0000 Subject: [PATCH 11/11] fix: restore three v6.0.0 regressions from Fern regen - Restore int types for speaker/channel/num_words (Fern changed to float) - Restore Union[str, Sequence[str]] array params in listen v1/v2 clients and listen_v1redact type (Fern narrowed to str-only) - Restore optional defaults on send methods across all 4 socket clients (send_finalize, send_close_stream, send_keep_alive, send_flush, send_clear, send_close) - Protect all manually-fixed files in .fernignore --- .fernignore | 16 +++++- src/deepgram/agent/v1/socket_client.py | 8 +-- src/deepgram/listen/v1/client.py | 56 +++++++++---------- src/deepgram/listen/v1/socket_client.py | 24 ++++---- src/deepgram/listen/v2/client.py | 20 ++++--- src/deepgram/listen/v2/socket_client.py | 8 +-- src/deepgram/speak/v1/socket_client.py | 24 ++++---- src/deepgram/types/listen_v1redact.py | 8 ++- ...natives_item_paragraphs_paragraphs_item.py | 4 +- ...sten_v1response_results_utterances_item.py | 4 +- ...onse_results_utterances_item_words_item.py | 2 +- 11 files changed, 98 insertions(+), 76 deletions(-) diff --git a/.fernignore b/.fernignore index 175f261b..cbea1734 100644 --- a/.fernignore +++ b/.fernignore @@ -14,12 +14,26 @@ tests/wire/test_listen_v1_media.py # WebSocket socket clients: # - Optional message parameter defaults for send_flush, send_close, send_clear, # send_finalize, send_close_stream, send_keep_alive -# - Removed unused imports (JSONDecodeError, websockets) flagged by ruff F401 +# - construct_type instead of parse_obj_as (skip_validation for unknown WS messages) +# - except Exception (broad catch for custom transports) +# - _sanitize_numeric_types in agent socket client (float→int for API) src/deepgram/speak/v1/socket_client.py src/deepgram/listen/v1/socket_client.py src/deepgram/listen/v2/socket_client.py src/deepgram/agent/v1/socket_client.py +# Type files with manual int type corrections (Fern generates float for speaker/channel/num_words) +src/deepgram/types/listen_v1response_results_utterances_item.py +src/deepgram/types/listen_v1response_results_utterances_item_words_item.py +src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py + +# Redact type with Union[str, Sequence[str]] support (Fern narrows to Union[Literal, Any]) +src/deepgram/types/listen_v1redact.py + +# Listen client files with Union[str, Sequence[str]] array param support +src/deepgram/listen/v1/client.py +src/deepgram/listen/v2/client.py + # Hand-written custom tests tests/custom/test_text_builder.py tests/custom/test_transport.py diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index a5a24f50..e486dc67 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -145,12 +145,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp """ await self._send_model(message) - async def send_keep_alive(self, message: AgentV1KeepAlive) -> None: + async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - await self._send_model(message) + await self._send_model(message or AgentV1KeepAlive()) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -262,12 +262,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) """ self._send_model(message) - def send_keep_alive(self, message: AgentV1KeepAlive) -> None: + def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a AgentV1KeepAlive. """ - self._send_model(message) + self._send_model(message or AgentV1KeepAlive()) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ diff --git a/src/deepgram/listen/v1/client.py b/src/deepgram/listen/v1/client.py index 6526f830..7dd8baf3 100644 --- a/src/deepgram/listen/v1/client.py +++ b/src/deepgram/listen/v1/client.py @@ -55,10 +55,10 @@ def connect( dictation: typing.Optional[str] = None, encoding: typing.Optional[str] = None, endpointing: typing.Optional[str] = None, - extra: typing.Optional[str] = None, + extra: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, interim_results: typing.Optional[str] = None, - keyterm: typing.Optional[str] = None, - keywords: typing.Optional[str] = None, + keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keywords: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, language: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, model: str, @@ -66,12 +66,12 @@ def connect( numerals: typing.Optional[str] = None, profanity_filter: typing.Optional[str] = None, punctuate: typing.Optional[str] = None, - redact: typing.Optional[str] = None, - replace: typing.Optional[str] = None, + redact: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + replace: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, sample_rate: typing.Optional[str] = None, - search: typing.Optional[str] = None, + search: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, smart_format: typing.Optional[str] = None, - tag: typing.Optional[str] = None, + tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, utterance_end_ms: typing.Optional[str] = None, vad_events: typing.Optional[str] = None, version: typing.Optional[str] = None, @@ -99,13 +99,13 @@ def connect( endpointing : typing.Optional[str] - extra : typing.Optional[str] + extra : typing.Optional[typing.Union[str, typing.Sequence[str]]] interim_results : typing.Optional[str] - keyterm : typing.Optional[str] + keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] - keywords : typing.Optional[str] + keywords : typing.Optional[typing.Union[str, typing.Sequence[str]]] language : typing.Optional[str] @@ -122,17 +122,17 @@ def connect( punctuate : typing.Optional[str] - redact : typing.Optional[str] + redact : typing.Optional[typing.Union[str, typing.Sequence[str]]] - replace : typing.Optional[str] + replace : typing.Optional[typing.Union[str, typing.Sequence[str]]] sample_rate : typing.Optional[str] - search : typing.Optional[str] + search : typing.Optional[typing.Union[str, typing.Sequence[str]]] smart_format : typing.Optional[str] - tag : typing.Optional[str] + tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] utterance_end_ms : typing.Optional[str] @@ -256,10 +256,10 @@ async def connect( dictation: typing.Optional[str] = None, encoding: typing.Optional[str] = None, endpointing: typing.Optional[str] = None, - extra: typing.Optional[str] = None, + extra: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, interim_results: typing.Optional[str] = None, - keyterm: typing.Optional[str] = None, - keywords: typing.Optional[str] = None, + keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + keywords: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, language: typing.Optional[str] = None, mip_opt_out: typing.Optional[str] = None, model: str, @@ -267,12 +267,12 @@ async def connect( numerals: typing.Optional[str] = None, profanity_filter: typing.Optional[str] = None, punctuate: typing.Optional[str] = None, - redact: typing.Optional[str] = None, - replace: typing.Optional[str] = None, + redact: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + replace: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, sample_rate: typing.Optional[str] = None, - search: typing.Optional[str] = None, + search: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, smart_format: typing.Optional[str] = None, - tag: typing.Optional[str] = None, + tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, utterance_end_ms: typing.Optional[str] = None, vad_events: typing.Optional[str] = None, version: typing.Optional[str] = None, @@ -300,13 +300,13 @@ async def connect( endpointing : typing.Optional[str] - extra : typing.Optional[str] + extra : typing.Optional[typing.Union[str, typing.Sequence[str]]] interim_results : typing.Optional[str] - keyterm : typing.Optional[str] + keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] - keywords : typing.Optional[str] + keywords : typing.Optional[typing.Union[str, typing.Sequence[str]]] language : typing.Optional[str] @@ -323,17 +323,17 @@ async def connect( punctuate : typing.Optional[str] - redact : typing.Optional[str] + redact : typing.Optional[typing.Union[str, typing.Sequence[str]]] - replace : typing.Optional[str] + replace : typing.Optional[typing.Union[str, typing.Sequence[str]]] sample_rate : typing.Optional[str] - search : typing.Optional[str] + search : typing.Optional[typing.Union[str, typing.Sequence[str]]] smart_format : typing.Optional[str] - tag : typing.Optional[str] + tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] utterance_end_ms : typing.Optional[str] diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index 68aa39bd..c16839d3 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -67,26 +67,26 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_finalize(self, message: ListenV1Finalize) -> None: + async def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - await self._send_model(message) + await self._send_model(message or ListenV1Finalize(type="Finalize")) - async def send_close_stream(self, message: ListenV1CloseStream) -> None: + async def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - await self._send_model(message) + await self._send_model(message or ListenV1CloseStream(type="CloseStream")) - async def send_keep_alive(self, message: ListenV1KeepAlive) -> None: + async def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - await self._send_model(message) + await self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) async def recv(self) -> V1SocketClientResponse: """ @@ -156,26 +156,26 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_finalize(self, message: ListenV1Finalize) -> None: + def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1Finalize. """ - self._send_model(message) + self._send_model(message or ListenV1Finalize(type="Finalize")) - def send_close_stream(self, message: ListenV1CloseStream) -> None: + def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1CloseStream. """ - self._send_model(message) + self._send_model(message or ListenV1CloseStream(type="CloseStream")) - def send_keep_alive(self, message: ListenV1KeepAlive) -> None: + def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV1KeepAlive. """ - self._send_model(message) + self._send_model(message or ListenV1KeepAlive(type="KeepAlive")) def recv(self) -> V1SocketClientResponse: """ diff --git a/src/deepgram/listen/v2/client.py b/src/deepgram/listen/v2/client.py index 9e85c73d..949f0c75 100644 --- a/src/deepgram/listen/v2/client.py +++ b/src/deepgram/listen/v2/client.py @@ -46,9 +46,9 @@ def connect( eager_eot_threshold: typing.Optional[str] = None, eot_threshold: typing.Optional[str] = None, eot_timeout_ms: typing.Optional[str] = None, - keyterm: typing.Optional[str] = None, + keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, mip_opt_out: typing.Optional[str] = None, - tag: typing.Optional[str] = None, + tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, authorization: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[V2SocketClient]: @@ -70,11 +70,13 @@ def connect( eot_timeout_ms : typing.Optional[str] - keyterm : typing.Optional[str] + keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Keyterm prompting can improve recognition of specialized terminology. Pass a single string or a list of strings. mip_opt_out : typing.Optional[str] - tag : typing.Optional[str] + tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Label your requests for the purpose of identification during usage reporting. Pass a single string or a list of strings. authorization : typing.Optional[str] Use your API key for authentication, or alternatively generate a [temporary token](/guides/fundamentals/token-based-authentication) and pass it via the `token` query parameter. @@ -161,9 +163,9 @@ async def connect( eager_eot_threshold: typing.Optional[str] = None, eot_threshold: typing.Optional[str] = None, eot_timeout_ms: typing.Optional[str] = None, - keyterm: typing.Optional[str] = None, + keyterm: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, mip_opt_out: typing.Optional[str] = None, - tag: typing.Optional[str] = None, + tag: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, authorization: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[AsyncV2SocketClient]: @@ -185,11 +187,13 @@ async def connect( eot_timeout_ms : typing.Optional[str] - keyterm : typing.Optional[str] + keyterm : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Keyterm prompting can improve recognition of specialized terminology. Pass a single string or a list of strings. mip_opt_out : typing.Optional[str] - tag : typing.Optional[str] + tag : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Label your requests for the purpose of identification during usage reporting. Pass a single string or a list of strings. authorization : typing.Optional[str] Use your API key for authentication, or alternatively generate a [temporary token](/guides/fundamentals/token-based-authentication) and pass it via the `token` query parameter. diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 293d5c05..136f7e74 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -64,12 +64,12 @@ async def send_media(self, message: bytes) -> None: """ await self._send(message) - async def send_close_stream(self, message: ListenV2CloseStream) -> None: + async def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - await self._send_model(message) + await self._send_model(message or ListenV2CloseStream(type="CloseStream")) async def recv(self) -> V2SocketClientResponse: """ @@ -139,12 +139,12 @@ def send_media(self, message: bytes) -> None: """ self._send(message) - def send_close_stream(self, message: ListenV2CloseStream) -> None: + def send_close_stream(self, message: typing.Optional[ListenV2CloseStream] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a ListenV2CloseStream. """ - self._send_model(message) + self._send_model(message or ListenV2CloseStream(type="CloseStream")) def recv(self) -> V2SocketClientResponse: """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index 82c1ac99..9f640575 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -68,26 +68,26 @@ async def send_text(self, message: SpeakV1Text) -> None: """ await self._send_model(message) - async def send_flush(self, message: SpeakV1Flush) -> None: + async def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Flush(type="Flush")) - async def send_clear(self, message: SpeakV1Clear) -> None: + async def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Clear(type="Clear")) - async def send_close(self, message: SpeakV1Close) -> None: + async def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - await self._send_model(message) + await self._send_model(message or SpeakV1Close(type="Close")) async def recv(self) -> V1SocketClientResponse: """ @@ -157,26 +157,26 @@ def send_text(self, message: SpeakV1Text) -> None: """ self._send_model(message) - def send_flush(self, message: SpeakV1Flush) -> None: + def send_flush(self, message: typing.Optional[SpeakV1Flush] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Flush. """ - self._send_model(message) + self._send_model(message or SpeakV1Flush(type="Flush")) - def send_clear(self, message: SpeakV1Clear) -> None: + def send_clear(self, message: typing.Optional[SpeakV1Clear] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Clear. """ - self._send_model(message) + self._send_model(message or SpeakV1Clear(type="Clear")) - def send_close(self, message: SpeakV1Close) -> None: + def send_close(self, message: typing.Optional[SpeakV1Close] = None) -> None: """ Send a message to the websocket connection. The message will be sent as a SpeakV1Close. """ - self._send_model(message) + self._send_model(message or SpeakV1Close(type="Close")) def recv(self) -> V1SocketClientResponse: """ diff --git a/src/deepgram/types/listen_v1redact.py b/src/deepgram/types/listen_v1redact.py index 7bf572f3..9187906c 100644 --- a/src/deepgram/types/listen_v1redact.py +++ b/src/deepgram/types/listen_v1redact.py @@ -2,6 +2,10 @@ import typing -ListenV1Redact = typing.Union[ - typing.Literal["true", "false", "pci", "numbers", "aggressive_numbers", "ssn"], typing.Any +ListenV1Redact = typing.Optional[ + typing.Union[ + typing.Literal["true", "false", "pci", "numbers", "aggressive_numbers", "ssn"], + str, + typing.Sequence[str], + ] ] diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py index a622d4ae..eec3866b 100644 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py @@ -14,8 +14,8 @@ class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsIte sentences: typing.Optional[ typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem] ] = None - speaker: typing.Optional[float] = None - num_words: typing.Optional[float] = None + speaker: typing.Optional[int] = None + num_words: typing.Optional[int] = None start: typing.Optional[float] = None end: typing.Optional[float] = None diff --git a/src/deepgram/types/listen_v1response_results_utterances_item.py b/src/deepgram/types/listen_v1response_results_utterances_item.py index ed8a8ddd..0947d9f5 100644 --- a/src/deepgram/types/listen_v1response_results_utterances_item.py +++ b/src/deepgram/types/listen_v1response_results_utterances_item.py @@ -12,10 +12,10 @@ class ListenV1ResponseResultsUtterancesItem(UncheckedBaseModel): start: typing.Optional[float] = None end: typing.Optional[float] = None confidence: typing.Optional[float] = None - channel: typing.Optional[float] = None + channel: typing.Optional[int] = None transcript: typing.Optional[str] = None words: typing.Optional[typing.List[ListenV1ResponseResultsUtterancesItemWordsItem]] = None - speaker: typing.Optional[float] = None + speaker: typing.Optional[int] = None id: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py index 716f2e2a..6cd1313a 100644 --- a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py +++ b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py @@ -12,7 +12,7 @@ class ListenV1ResponseResultsUtterancesItemWordsItem(UncheckedBaseModel): start: typing.Optional[float] = None end: typing.Optional[float] = None confidence: typing.Optional[float] = None - speaker: typing.Optional[float] = None + speaker: typing.Optional[int] = None speaker_confidence: typing.Optional[float] = None punctuated_word: typing.Optional[str] = None