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