From 0bfb1b5af7050db41eaaaebcd49f85974ee4e987 Mon Sep 17 00:00:00 2001 From: Greg Holmes Date: Mon, 20 Apr 2026 16:30:05 +0100 Subject: [PATCH 1/5] chore: SDK regeneration 2026-04-20 From 8020a628890f23832b83d7a153355e2f8622488f Mon Sep 17 00:00:00 2001 From: Greg Holmes Date: Mon, 20 Apr 2026 16:31:58 +0100 Subject: [PATCH 2/5] chore: unfreeze files pending regen --- .fernignore | 14 +- src/deepgram/agent/v1/socket_client.py.bak | 357 ++++++++++++++++++ src/deepgram/listen/v1/socket_client.py.bak | 234 ++++++++++++ src/deepgram/listen/v2/socket_client.py.bak | 220 +++++++++++ src/deepgram/speak/v1/socket_client.py.bak | 235 ++++++++++++ ...ves_item_paragraphs_paragraphs_item.py.bak | 29 ++ ..._v1response_results_utterances_item.py.bak | 28 ++ ..._results_utterances_item_words_item.py.bak | 26 ++ 8 files changed, 1136 insertions(+), 7 deletions(-) create mode 100644 src/deepgram/agent/v1/socket_client.py.bak create mode 100644 src/deepgram/listen/v1/socket_client.py.bak create mode 100644 src/deepgram/listen/v2/socket_client.py.bak create mode 100644 src/deepgram/speak/v1/socket_client.py.bak create mode 100644 src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak create mode 100644 src/deepgram/types/listen_v1response_results_utterances_item.py.bak create mode 100644 src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak diff --git a/.fernignore b/.fernignore index 95cce1f0..416c8831 100644 --- a/.fernignore +++ b/.fernignore @@ -11,16 +11,16 @@ src/deepgram/client.py # - optional message param on control send_ methods (send_keep_alive, send_close_stream, etc.) # so users don't need to instantiate the type themselves for no-payload control messages # [temporarily frozen — generator bugs in construct_type call convention and exception handling] -src/deepgram/agent/v1/socket_client.py -src/deepgram/listen/v1/socket_client.py -src/deepgram/listen/v2/socket_client.py -src/deepgram/speak/v1/socket_client.py +src/deepgram/agent/v1/socket_client.py.bak +src/deepgram/listen/v1/socket_client.py.bak +src/deepgram/listen/v2/socket_client.py.bak +src/deepgram/speak/v1/socket_client.py.bak # Type files with manual int type corrections (Fern generates float for speaker/channel/num_words) # [temporarily frozen — waiting on internal-api-specs#205] -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 +src/deepgram/types/listen_v1response_results_utterances_item.py.bak +src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak +src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak # Hand-written custom tests tests/custom/test_text_builder.py diff --git a/src/deepgram/agent/v1/socket_client.py.bak b/src/deepgram/agent/v1/socket_client.py.bak new file mode 100644 index 00000000..21b30ec1 --- /dev/null +++ b/src/deepgram/agent/v1/socket_client.py.bak @@ -0,0 +1,357 @@ +# This file was auto-generated by Fern from our API Definition. + +import json +import logging +import typing + +import websockets.sync.connection as websockets_sync_connection +from ...core.events import EventEmitterMixin, EventType +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 +from .types.agent_v1conversation_text import AgentV1ConversationText +from .types.agent_v1error import AgentV1Error +from .types.agent_v1function_call_request import AgentV1FunctionCallRequest +from .types.agent_v1inject_agent_message import AgentV1InjectAgentMessage +from .types.agent_v1inject_user_message import AgentV1InjectUserMessage +from .types.agent_v1injection_refused import AgentV1InjectionRefused +from .types.agent_v1keep_alive import AgentV1KeepAlive +from .types.agent_v1prompt_updated import AgentV1PromptUpdated +from .types.agent_v1receive_function_call_response import AgentV1ReceiveFunctionCallResponse +from .types.agent_v1send_function_call_response import AgentV1SendFunctionCallResponse +from .types.agent_v1settings import AgentV1Settings +from .types.agent_v1settings_applied import AgentV1SettingsApplied +from .types.agent_v1speak_updated import AgentV1SpeakUpdated +from .types.agent_v1think_updated import AgentV1ThinkUpdated +from .types.agent_v1update_prompt import AgentV1UpdatePrompt +from .types.agent_v1update_speak import AgentV1UpdateSpeak +from .types.agent_v1update_think import AgentV1UpdateThink +from .types.agent_v1user_started_speaking import AgentV1UserStartedSpeaking +from .types.agent_v1warning import AgentV1Warning +from .types.agent_v1welcome import AgentV1Welcome + +try: + from websockets.legacy.client import WebSocketClientProtocol # type: ignore +except ImportError: + from websockets import WebSocketClientProtocol # type: ignore + +_logger = logging.getLogger(__name__) + + +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, + AgentV1SpeakUpdated, + AgentV1ThinkUpdated, + AgentV1InjectionRefused, + AgentV1Welcome, + AgentV1SettingsApplied, + AgentV1ConversationText, + AgentV1UserStartedSpeaking, + AgentV1AgentThinking, + AgentV1FunctionCallRequest, + AgentV1AgentStartedSpeaking, + AgentV1AgentAudioDone, + AgentV1Error, + AgentV1Warning, + bytes, +] + + +class AsyncV1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: WebSocketClientProtocol): + super().__init__() + self._websocket = websocket + + async def __aiter__(self): + async for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + async def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + await self._emit_async(EventType.OPEN, None) + try: + async for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + await self._emit_async(EventType.MESSAGE, parsed) + except Exception as exc: + await self._emit_async(EventType.ERROR, exc) + finally: + await self._emit_async(EventType.CLOSE, None) + + async def send_settings(self, message: AgentV1Settings) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1Settings. + """ + await self._send_model(message) + + async def send_update_speak(self, message: AgentV1UpdateSpeak) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdateSpeak. + """ + await self._send_model(message) + + async def send_inject_user_message(self, message: AgentV1InjectUserMessage) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1InjectUserMessage. + """ + await self._send_model(message) + + async def send_inject_agent_message(self, message: AgentV1InjectAgentMessage) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1InjectAgentMessage. + """ + await self._send_model(message) + + async def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1SendFunctionCallResponse. + """ + await self._send_model(message) + + 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 or AgentV1KeepAlive(type="KeepAlive")) + + async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdatePrompt. + """ + await self._send_model(message) + + async def send_update_think(self, message: AgentV1UpdateThink) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdateThink. + """ + await self._send_model(message) + + async def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + await self._send(message) + + async def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = await self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + async def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + await self._websocket.send(data) + + 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())) + + +class V1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: websockets_sync_connection.Connection): + super().__init__() + self._websocket = websocket + + def __iter__(self): + for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + self._emit(EventType.OPEN, None) + try: + for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + self._emit(EventType.MESSAGE, parsed) + except Exception as exc: + self._emit(EventType.ERROR, exc) + finally: + self._emit(EventType.CLOSE, None) + + def send_settings(self, message: AgentV1Settings) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1Settings. + """ + self._send_model(message) + + def send_update_speak(self, message: AgentV1UpdateSpeak) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdateSpeak. + """ + self._send_model(message) + + def send_inject_user_message(self, message: AgentV1InjectUserMessage) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1InjectUserMessage. + """ + self._send_model(message) + + def send_inject_agent_message(self, message: AgentV1InjectAgentMessage) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1InjectAgentMessage. + """ + self._send_model(message) + + def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1SendFunctionCallResponse. + """ + self._send_model(message) + + 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 or AgentV1KeepAlive(type="KeepAlive")) + + def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdatePrompt. + """ + self._send_model(message) + + def send_update_think(self, message: AgentV1UpdateThink) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a AgentV1UpdateThink. + """ + self._send_model(message) + + def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + self._send(message) + + def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + self._websocket.send(data) + + def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + self._send(_sanitize_numeric_types(data.dict())) diff --git a/src/deepgram/listen/v1/socket_client.py.bak b/src/deepgram/listen/v1/socket_client.py.bak new file mode 100644 index 00000000..5954d116 --- /dev/null +++ b/src/deepgram/listen/v1/socket_client.py.bak @@ -0,0 +1,234 @@ +# This file was auto-generated by Fern from our API Definition. + +import json +import logging +import typing + +import websockets.sync.connection as websockets_sync_connection +from ...core.events import EventEmitterMixin, EventType +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 +from .types.listen_v1metadata import ListenV1Metadata +from .types.listen_v1results import ListenV1Results +from .types.listen_v1speech_started import ListenV1SpeechStarted +from .types.listen_v1utterance_end import ListenV1UtteranceEnd + +try: + from websockets.legacy.client import WebSocketClientProtocol # type: ignore +except ImportError: + from websockets import WebSocketClientProtocol # type: ignore + +_logger = logging.getLogger(__name__) +V1SocketClientResponse = typing.Union[ListenV1Results, ListenV1Metadata, ListenV1UtteranceEnd, ListenV1SpeechStarted] + + +class AsyncV1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: WebSocketClientProtocol): + super().__init__() + self._websocket = websocket + + async def __aiter__(self): + async for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + async def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + await self._emit_async(EventType.OPEN, None) + try: + async for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + await self._emit_async(EventType.MESSAGE, parsed) + except Exception as exc: + await self._emit_async(EventType.ERROR, exc) + finally: + await self._emit_async(EventType.CLOSE, None) + + async def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + await self._send(message) + + 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 or ListenV1Finalize(type="Finalize")) + + 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 or ListenV1CloseStream(type="CloseStream")) + + 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 or ListenV1KeepAlive(type="KeepAlive")) + + async def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = await self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + async def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + await self._websocket.send(data) + + async def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + await self._send(data.dict()) + + +class V1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: websockets_sync_connection.Connection): + super().__init__() + self._websocket = websocket + + def __iter__(self): + for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + self._emit(EventType.OPEN, None) + try: + for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + self._emit(EventType.MESSAGE, parsed) + except Exception as exc: + self._emit(EventType.ERROR, exc) + finally: + self._emit(EventType.CLOSE, None) + + def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + self._send(message) + + 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 or ListenV1Finalize(type="Finalize")) + + 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 or ListenV1CloseStream(type="CloseStream")) + + 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 or ListenV1KeepAlive(type="KeepAlive")) + + def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + self._websocket.send(data) + + def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + self._send(data.dict()) diff --git a/src/deepgram/listen/v2/socket_client.py.bak b/src/deepgram/listen/v2/socket_client.py.bak new file mode 100644 index 00000000..d214f0f5 --- /dev/null +++ b/src/deepgram/listen/v2/socket_client.py.bak @@ -0,0 +1,220 @@ +# This file was auto-generated by Fern from our API Definition. + +import json +import logging +import typing + +import websockets.sync.connection as websockets_sync_connection +from ...core.events import EventEmitterMixin, EventType +from ...core.unchecked_base_model import construct_type +from .types.listen_v2close_stream import ListenV2CloseStream +from .types.listen_v2configure_failure import ListenV2ConfigureFailure +from .types.listen_v2connected import ListenV2Connected +from .types.listen_v2fatal_error import ListenV2FatalError +from .types.listen_v2turn_info import ListenV2TurnInfo + +try: + from websockets.legacy.client import WebSocketClientProtocol # type: ignore +except ImportError: + from websockets import WebSocketClientProtocol # type: ignore + +_logger = logging.getLogger(__name__) +V2SocketClientResponse = typing.Union[ + ListenV2Connected, ListenV2TurnInfo, typing.Any, ListenV2ConfigureFailure, ListenV2FatalError +] + + +class AsyncV2SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: WebSocketClientProtocol): + super().__init__() + self._websocket = websocket + + async def __aiter__(self): + async for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + async def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + await self._emit_async(EventType.OPEN, None) + try: + async for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + await self._emit_async(EventType.MESSAGE, parsed) + except Exception as exc: + await self._emit_async(EventType.ERROR, exc) + finally: + await self._emit_async(EventType.CLOSE, None) + + async def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + await self._send(message) + + 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 or ListenV2CloseStream(type="CloseStream")) + + async def send_configure(self, message: typing.Any) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a typing.Any. + """ + await self._send(message) + + async def recv(self) -> V2SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = await self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + async def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + await self._websocket.send(data) + + async def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + await self._send(data.dict()) + + +class V2SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: websockets_sync_connection.Connection): + super().__init__() + self._websocket = websocket + + def __iter__(self): + for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + self._emit(EventType.OPEN, None) + try: + for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + self._emit(EventType.MESSAGE, parsed) + except Exception as exc: + self._emit(EventType.ERROR, exc) + finally: + self._emit(EventType.CLOSE, None) + + def send_media(self, message: bytes) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a bytes. + """ + self._send(message) + + 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 or ListenV2CloseStream(type="CloseStream")) + + def send_configure(self, message: typing.Any) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a typing.Any. + """ + self._send(message) + + def recv(self) -> V2SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + self._websocket.send(data) + + def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + self._send(data.dict()) diff --git a/src/deepgram/speak/v1/socket_client.py.bak b/src/deepgram/speak/v1/socket_client.py.bak new file mode 100644 index 00000000..e3c28bb5 --- /dev/null +++ b/src/deepgram/speak/v1/socket_client.py.bak @@ -0,0 +1,235 @@ +# This file was auto-generated by Fern from our API Definition. + +import json +import logging +import typing + +import websockets.sync.connection as websockets_sync_connection +from ...core.events import EventEmitterMixin, EventType +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 +from .types.speak_v1flush import SpeakV1Flush +from .types.speak_v1flushed import SpeakV1Flushed +from .types.speak_v1metadata import SpeakV1Metadata +from .types.speak_v1text import SpeakV1Text +from .types.speak_v1warning import SpeakV1Warning + +try: + from websockets.legacy.client import WebSocketClientProtocol # type: ignore +except ImportError: + from websockets import WebSocketClientProtocol # type: ignore + +_logger = logging.getLogger(__name__) +V1SocketClientResponse = typing.Union[bytes, SpeakV1Metadata, SpeakV1Flushed, SpeakV1Cleared, SpeakV1Warning] + + +class AsyncV1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: WebSocketClientProtocol): + super().__init__() + self._websocket = websocket + + async def __aiter__(self): + async for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + async def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + await self._emit_async(EventType.OPEN, None) + try: + async for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + await self._emit_async(EventType.MESSAGE, parsed) + except Exception as exc: + await self._emit_async(EventType.ERROR, exc) + finally: + await self._emit_async(EventType.CLOSE, None) + + async def send_text(self, message: SpeakV1Text) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a SpeakV1Text. + """ + await self._send_model(message) + + 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 or SpeakV1Flush(type="Flush")) + + 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 or SpeakV1Clear(type="Clear")) + + 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 or SpeakV1Close(type="Close")) + + async def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = await self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + async def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + await self._websocket.send(data) + + async def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + await self._send(data.dict()) + + +class V1SocketClient(EventEmitterMixin): + def __init__(self, *, websocket: websockets_sync_connection.Connection): + super().__init__() + self._websocket = websocket + + def __iter__(self): + for message in self._websocket: + if isinstance(message, bytes): + yield message + else: + try: + yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + + def start_listening(self): + """ + Start listening for messages on the websocket connection. + + Emits events in the following order: + - EventType.OPEN when connection is established + - EventType.MESSAGE for each message received + - EventType.ERROR if an error occurs + - EventType.CLOSE when connection is closed + """ + self._emit(EventType.OPEN, None) + try: + for raw_message in self._websocket: + if isinstance(raw_message, bytes): + parsed = raw_message + else: + json_data = json.loads(raw_message) + try: + parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning( + "Skipping unknown WebSocket message; update your SDK version to support new message types." + ) + continue + self._emit(EventType.MESSAGE, parsed) + except Exception as exc: + self._emit(EventType.ERROR, exc) + finally: + self._emit(EventType.CLOSE, None) + + def send_text(self, message: SpeakV1Text) -> None: + """ + Send a message to the websocket connection. + The message will be sent as a SpeakV1Text. + """ + self._send_model(message) + + 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 or SpeakV1Flush(type="Flush")) + + 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 or SpeakV1Clear(type="Clear")) + + 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 or SpeakV1Close(type="Close")) + + def recv(self) -> V1SocketClientResponse: + """ + Receive a message from the websocket connection. + """ + data = self._websocket.recv() + if isinstance(data, bytes): + return data # type: ignore + json_data = json.loads(data) + try: + return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore + except Exception: + _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") + return json_data # type: ignore + + def _send(self, data: typing.Any) -> None: + """ + Send a message to the websocket connection. + """ + if isinstance(data, dict): + data = json.dumps(data) + self._websocket.send(data) + + def _send_model(self, data: typing.Any) -> None: + """ + Send a Pydantic model to the websocket connection. + """ + self._send(data.dict()) diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak new file mode 100644 index 00000000..eec3866b --- /dev/null +++ b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +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(UncheckedBaseModel): + sentences: typing.Optional[ + typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem] + ] = None + speaker: typing.Optional[int] = None + num_words: typing.Optional[int] = None + start: typing.Optional[float] = None + end: typing.Optional[float] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/types/listen_v1response_results_utterances_item.py.bak b/src/deepgram/types/listen_v1response_results_utterances_item.py.bak new file mode 100644 index 00000000..0947d9f5 --- /dev/null +++ b/src/deepgram/types/listen_v1response_results_utterances_item.py.bak @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +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(UncheckedBaseModel): + start: typing.Optional[float] = None + end: typing.Optional[float] = None + confidence: typing.Optional[float] = None + channel: typing.Optional[int] = None + transcript: typing.Optional[str] = None + words: typing.Optional[typing.List[ListenV1ResponseResultsUtterancesItemWordsItem]] = None + speaker: typing.Optional[int] = None + id: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak new file mode 100644 index 00000000..6cd1313a --- /dev/null +++ b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.unchecked_base_model import UncheckedBaseModel + + +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_confidence: typing.Optional[float] = None + punctuated_word: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow From a2243a3a86db0aa5d8f7a1ab6a5cfa58bd8b65a0 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:17:47 +0000 Subject: [PATCH 3/5] SDK regeneration --- .fern/metadata.json | 10 +- poetry.lock | 1372 ++++++++-- pyproject.toml | 23 +- requirements.txt | 2 +- src/deepgram/__init__.py | 5 + src/deepgram/_default_clients.py | 32 + .../requests/agent_v1settings_audio_input.py | 2 +- .../requests/agent_v1settings_audio_output.py | 4 +- .../v1/settings/think/models/raw_client.py | 14 +- src/deepgram/agent/v1/socket_client.py | 38 +- .../v1/types/agent_v1settings_audio_input.py | 2 +- .../v1/types/agent_v1settings_audio_output.py | 4 +- src/deepgram/auth/v1/tokens/raw_client.py | 10 + src/deepgram/base_client.py | 22 +- src/deepgram/core/__init__.py | 7 +- src/deepgram/core/http_client.py | 108 +- src/deepgram/core/jsonable_encoder.py | 12 + src/deepgram/core/parse_error.py | 36 + src/deepgram/core/pydantic_utilities.py | 83 +- src/deepgram/core/unchecked_base_model.py | 199 +- src/deepgram/environment.py | 4 - src/deepgram/listen/__init__.py | 24 + src/deepgram/listen/v1/media/client.py | 2 + src/deepgram/listen/v1/media/raw_client.py | 18 + .../listen/v1/requests/listen_v1metadata.py | 2 +- .../listen/v1/requests/listen_v1results.py | 2 +- ...ts_channel_alternatives_item_words_item.py | 2 +- .../v1/requests/listen_v1speech_started.py | 2 +- .../v1/requests/listen_v1utterance_end.py | 2 +- src/deepgram/listen/v1/socket_client.py | 30 +- .../listen/v1/types/listen_v1metadata.py | 2 +- .../listen/v1/types/listen_v1results.py | 2 +- ...ts_channel_alternatives_item_words_item.py | 2 +- .../v1/types/listen_v1speech_started.py | 2 +- .../listen/v1/types/listen_v1utterance_end.py | 2 +- src/deepgram/listen/v2/__init__.py | 24 + src/deepgram/listen/v2/requests/__init__.py | 12 + .../listen/v2/requests/listen_v2configure.py | 28 + .../v2/requests/listen_v2configure_failure.py | 2 +- .../v2/requests/listen_v2configure_success.py | 33 + .../listen_v2configure_success_thresholds.py | 17 + .../requests/listen_v2configure_thresholds.py | 17 + .../listen/v2/requests/listen_v2connected.py | 2 +- .../v2/requests/listen_v2fatal_error.py | 2 +- .../listen/v2/requests/listen_v2turn_info.py | 4 +- src/deepgram/listen/v2/socket_client.py | 30 +- src/deepgram/listen/v2/types/__init__.py | 12 + .../listen/v2/types/listen_v2configure.py | 39 + .../v2/types/listen_v2configure_failure.py | 2 +- .../v2/types/listen_v2configure_success.py | 44 + .../listen_v2configure_success_thresholds.py | 30 + .../v2/types/listen_v2configure_thresholds.py | 30 + .../listen/v2/types/listen_v2connected.py | 2 +- .../listen/v2/types/listen_v2fatal_error.py | 2 +- .../listen/v2/types/listen_v2turn_info.py | 4 +- src/deepgram/manage/v1/models/raw_client.py | 24 +- .../projects/billing/balances/raw_client.py | 28 +- .../v1/projects/billing/breakdown/client.py | 2 + .../projects/billing/breakdown/raw_client.py | 16 +- .../v1/projects/billing/fields/raw_client.py | 16 +- .../projects/billing/purchases/raw_client.py | 16 +- .../manage/v1/projects/keys/raw_client.py | 52 +- .../v1/projects/members/invites/raw_client.py | 40 +- .../manage/v1/projects/members/raw_client.py | 28 +- .../v1/projects/members/scopes/raw_client.py | 28 +- .../manage/v1/projects/models/raw_client.py | 28 +- src/deepgram/manage/v1/projects/raw_client.py | 60 +- .../manage/v1/projects/requests/raw_client.py | 28 +- .../v1/projects/usage/breakdown/raw_client.py | 16 +- .../v1/projects/usage/fields/raw_client.py | 16 +- .../manage/v1/projects/usage/raw_client.py | 16 +- src/deepgram/read/v1/text/raw_client.py | 10 + .../requests/listen_v1response_metadata.py | 2 +- ...listen_v1response_metadata_intents_info.py | 4 +- ...sten_v1response_metadata_sentiment_info.py | 4 +- ...listen_v1response_metadata_summary_info.py | 4 +- .../listen_v1response_metadata_topics_info.py | 4 +- ...natives_item_paragraphs_paragraphs_item.py | 4 +- ...sten_v1response_results_utterances_item.py | 4 +- ...onse_results_utterances_item_words_item.py | 2 +- ...response_metadata_metadata_intents_info.py | 4 +- ...sponse_metadata_metadata_sentiment_info.py | 4 +- ...response_metadata_metadata_summary_info.py | 4 +- ...1response_metadata_metadata_topics_info.py | 4 +- .../v1/distribution_credentials/client.py | 2 + .../v1/distribution_credentials/raw_client.py | 52 +- src/deepgram/speak/v1/audio/raw_client.py | 16 + .../speak/v1/requests/speak_v1cleared.py | 2 +- .../speak/v1/requests/speak_v1flushed.py | 2 +- src/deepgram/speak/v1/socket_client.py | 30 +- .../speak/v1/types/speak_v1cleared.py | 2 +- .../speak/v1/types/speak_v1flushed.py | 2 +- .../delete_agent_configuration_v1response.py | 3 + .../types/delete_agent_variable_v1response.py | 3 + src/deepgram/types/listen_v1callback.py | 3 + src/deepgram/types/listen_v1channels.py | 3 + src/deepgram/types/listen_v1endpointing.py | 3 + src/deepgram/types/listen_v1extra.py | 3 + src/deepgram/types/listen_v1keyterm.py | 3 + src/deepgram/types/listen_v1keywords.py | 3 + src/deepgram/types/listen_v1language.py | 3 + src/deepgram/types/listen_v1mip_opt_out.py | 3 + src/deepgram/types/listen_v1replace.py | 3 + src/deepgram/types/listen_v1request_file.py | 3 + .../types/listen_v1response_metadata.py | 2 +- ...listen_v1response_metadata_intents_info.py | 4 +- ...sten_v1response_metadata_sentiment_info.py | 4 +- ...listen_v1response_metadata_summary_info.py | 4 +- .../listen_v1response_metadata_topics_info.py | 4 +- src/deepgram/types/listen_v1sample_rate.py | 3 + src/deepgram/types/listen_v1search.py | 3 + src/deepgram/types/listen_v1tag.py | 3 + .../types/listen_v1utterance_end_ms.py | 3 + src/deepgram/types/listen_v1version.py | 3 + .../types/listen_v2eager_eot_threshold.py | 5 + src/deepgram/types/listen_v2eot_threshold.py | 4 + src/deepgram/types/listen_v2eot_timeout_ms.py | 4 + src/deepgram/types/listen_v2mip_opt_out.py | 5 + src/deepgram/types/listen_v2sample_rate.py | 3 + src/deepgram/types/listen_v2tag.py | 4 + ...response_metadata_metadata_intents_info.py | 4 +- ...sponse_metadata_metadata_sentiment_info.py | 4 +- ...response_metadata_metadata_summary_info.py | 4 +- ...1response_metadata_metadata_topics_info.py | 4 +- src/deepgram/types/speak_v1mip_opt_out.py | 3 + .../voice_agent/configurations/raw_client.py | 64 +- .../voice_agent/variables/raw_client.py | 64 +- tests/conftest.py | 36 +- tests/test_aiohttp_autodetect.py | 116 + tests/utils/test_http_client.py | 362 +++ tests/wire/conftest.py | 9 +- tests/wire/test_listen_v1_media.py | 2 + ...st_manage_v1_projects_billing_breakdown.py | 2 + ...t_selfHosted_v1_distributionCredentials.py | 3 +- wiremock/wiremock-mappings.json | 2327 ++++++++++++++++- 135 files changed, 5460 insertions(+), 633 deletions(-) create mode 100644 src/deepgram/_default_clients.py create mode 100644 src/deepgram/core/parse_error.py create mode 100644 src/deepgram/listen/v2/requests/listen_v2configure.py create mode 100644 src/deepgram/listen/v2/requests/listen_v2configure_success.py create mode 100644 src/deepgram/listen/v2/requests/listen_v2configure_success_thresholds.py create mode 100644 src/deepgram/listen/v2/requests/listen_v2configure_thresholds.py create mode 100644 src/deepgram/listen/v2/types/listen_v2configure.py create mode 100644 src/deepgram/listen/v2/types/listen_v2configure_success.py create mode 100644 src/deepgram/listen/v2/types/listen_v2configure_success_thresholds.py create mode 100644 src/deepgram/listen/v2/types/listen_v2configure_thresholds.py create mode 100644 tests/test_aiohttp_autodetect.py diff --git a/.fern/metadata.json b/.fern/metadata.json index 00c1530d..f7ff8c0e 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,7 +1,7 @@ { - "cliVersion": "4.67.1", + "cliVersion": "4.84.2", "generatorName": "fernapi/fern-python-sdk", - "generatorVersion": "4.62.0", + "generatorVersion": "5.5.8", "generatorConfig": { "client": { "class_name": "BaseClient", @@ -16,6 +16,10 @@ "skip_validation": true } }, - "originGitCommit": "aa8e0677bcaea82c02a5934c61d195b35921b33d", + "originGitCommit": "dd25a2c9f4ba3da8f5b54812a7894b5ec7e17b62", + "originGitCommitIsDirty": true, + "invokedBy": "manual", + "requestedVersion": null, + "ciProvider": null, "sdkVersion": "6.1.2" } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index ab52d826..06f6fd63 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,173 @@ # This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +description = "Happy Eyeballs for asyncio" +optional = true +python-versions = ">=3.9" +files = [ + {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"}, + {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"}, +] + +[[package]] +name = "aiohttp" +version = "3.13.5" +description = "Async http client/server framework (asyncio)" +optional = true +python-versions = ">=3.9" +files = [ + {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b"}, + {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5"}, + {file = "aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95"}, + {file = "aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e"}, + {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7"}, + {file = "aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9"}, + {file = "aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76"}, + {file = "aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6"}, + {file = "aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d"}, + {file = "aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc"}, + {file = "aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac"}, + {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3"}, + {file = "aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06"}, + {file = "aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8"}, + {file = "aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9"}, + {file = "aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416"}, + {file = "aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1"}, + {file = "aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe"}, + {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14"}, + {file = "aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3"}, + {file = "aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1"}, + {file = "aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61"}, + {file = "aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832"}, + {file = "aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665"}, + {file = "aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6"}, + {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c"}, + {file = "aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc"}, + {file = "aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83"}, + {file = "aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c"}, + {file = "aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be"}, + {file = "aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b"}, + {file = "aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1"}, + {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b"}, + {file = "aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3"}, + {file = "aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162"}, + {file = "aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a"}, + {file = "aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254"}, + {file = "aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a"}, + {file = "aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500"}, + {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9"}, + {file = "aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8"}, + {file = "aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9"}, + {file = "aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf"}, + {file = "aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1"}, + {file = "aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258"}, + {file = "aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f"}, + {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b"}, + {file = "aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83"}, + {file = "aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67"}, + {file = "aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1"}, +] + +[package.dependencies] +aiohappyeyeballs = ">=2.5.0" +aiosignal = ">=1.4.0" +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +propcache = ">=0.2.0" +yarl = ">=1.17.0,<2.0" + +[package.extras] +speedups = ["Brotli (>=1.2)", "aiodns (>=3.3.0)", "backports.zstd", "brotlicffi (>=1.2)"] + +[[package]] +name = "aiosignal" +version = "1.4.0" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = true +python-versions = ">=3.9" +files = [ + {file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"}, + {file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" +typing-extensions = {version = ">=4.2", markers = "python_version < \"3.13\""} + [[package]] name = "annotated-types" version = "0.7.0" @@ -11,30 +179,57 @@ files = [ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "anyio" -version = "4.5.2" -description = "High level compatibility layer for multiple asynchronous event loop implementations" +version = "4.13.0" +description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, - {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, + {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, + {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] -trio = ["trio (>=0.26.1)"] +trio = ["trio (>=0.32.0)"] + +[[package]] +name = "async-timeout" +version = "5.0.1" +description = "Timeout context manager for asyncio programs" +optional = true +python-versions = ">=3.8" +files = [ + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, +] + +[[package]] +name = "attrs" +version = "26.1.0" +description = "Classes Without Boilerplate" +optional = true +python-versions = ">=3.9" +files = [ + {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, + {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, +] + +[[package]] +name = "backports-asyncio-runner" +version = "1.2.0" +description = "Backport of asyncio.Runner, a context manager that controls event loop life cycle." +optional = false +python-versions = "<3.11,>=3.8" +files = [ + {file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}, + {file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}, +] [[package]] name = "certifi" @@ -227,6 +422,145 @@ files = [ [package.extras] testing = ["hatch", "pre-commit", "pytest", "tox"] +[[package]] +name = "frozenlist" +version = "1.8.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = true +python-versions = ">=3.9" +files = [ + {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011"}, + {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565"}, + {file = "frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad"}, + {file = "frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2"}, + {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186"}, + {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e"}, + {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450"}, + {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef"}, + {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4"}, + {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff"}, + {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c"}, + {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f"}, + {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7"}, + {file = "frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a"}, + {file = "frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6"}, + {file = "frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967"}, + {file = "frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25"}, + {file = "frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b"}, + {file = "frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa"}, + {file = "frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf"}, + {file = "frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746"}, + {file = "frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd"}, + {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a"}, + {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7"}, + {file = "frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40"}, + {file = "frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027"}, + {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822"}, + {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121"}, + {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5"}, + {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e"}, + {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11"}, + {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1"}, + {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1"}, + {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8"}, + {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed"}, + {file = "frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496"}, + {file = "frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231"}, + {file = "frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62"}, + {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94"}, + {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c"}, + {file = "frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52"}, + {file = "frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51"}, + {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65"}, + {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82"}, + {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714"}, + {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d"}, + {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506"}, + {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51"}, + {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e"}, + {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0"}, + {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41"}, + {file = "frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b"}, + {file = "frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888"}, + {file = "frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042"}, + {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0"}, + {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f"}, + {file = "frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c"}, + {file = "frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2"}, + {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8"}, + {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686"}, + {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e"}, + {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a"}, + {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128"}, + {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f"}, + {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7"}, + {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30"}, + {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7"}, + {file = "frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806"}, + {file = "frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0"}, + {file = "frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b"}, + {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d"}, + {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed"}, + {file = "frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930"}, + {file = "frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c"}, + {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24"}, + {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37"}, + {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a"}, + {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2"}, + {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef"}, + {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe"}, + {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8"}, + {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a"}, + {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e"}, + {file = "frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df"}, + {file = "frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd"}, + {file = "frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79"}, + {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47"}, + {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca"}, + {file = "frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068"}, + {file = "frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95"}, + {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459"}, + {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675"}, + {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61"}, + {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6"}, + {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5"}, + {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3"}, + {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1"}, + {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178"}, + {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda"}, + {file = "frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087"}, + {file = "frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a"}, + {file = "frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103"}, + {file = "frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d"}, + {file = "frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad"}, +] + [[package]] name = "h11" version = "0.16.0" @@ -283,31 +617,204 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "httpx-aiohttp" +version = "0.1.8" +description = "Aiohttp transport for HTTPX" +optional = true +python-versions = ">=3.8" +files = [ + {file = "httpx_aiohttp-0.1.8-py3-none-any.whl", hash = "sha256:b7bd958d1331f3759a38a0ba22ad29832cb63ca69498c17735228055bf78fa7e"}, + {file = "httpx_aiohttp-0.1.8.tar.gz", hash = "sha256:756c5e74cdb568c3248ba63fe82bfe8bbe64b928728720f7eaac64b3cf46f308"}, +] + +[package.dependencies] +aiohttp = ">=3.10.0,<4" +httpx = ">=0.27.0" + [[package]] name = "idna" -version = "3.11" +version = "3.12" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" files = [ - {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, - {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, + {file = "idna-3.12-py3-none-any.whl", hash = "sha256:60ffaa1858fac94c9c124728c24fcde8160f3fb4a7f79aa8cdd33a9d1af60a67"}, + {file = "idna-3.12.tar.gz", hash = "sha256:724e9952cc9e2bd7550ea784adb098d837ab5267ef67a1ab9cf7846bdbdd8254"}, ] [package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" -version = "2.1.0" +version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +files = [ + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, +] + +[[package]] +name = "multidict" +version = "6.7.1" +description = "multidict implementation" +optional = true +python-versions = ">=3.9" files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, + {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5"}, + {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8"}, + {file = "multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190"}, + {file = "multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962"}, + {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505"}, + {file = "multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122"}, + {file = "multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df"}, + {file = "multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db"}, + {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d"}, + {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e"}, + {file = "multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0"}, + {file = "multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0"}, + {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa"}, + {file = "multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a"}, + {file = "multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b"}, + {file = "multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6"}, + {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172"}, + {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd"}, + {file = "multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a"}, + {file = "multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a"}, + {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba"}, + {file = "multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511"}, + {file = "multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19"}, + {file = "multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf"}, + {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23"}, + {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2"}, + {file = "multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed"}, + {file = "multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d"}, + {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33"}, + {file = "multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3"}, + {file = "multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5"}, + {file = "multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df"}, + {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1"}, + {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963"}, + {file = "multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd"}, + {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52"}, + {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108"}, + {file = "multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32"}, + {file = "multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8"}, + {file = "multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118"}, + {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee"}, + {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2"}, + {file = "multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37"}, + {file = "multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1"}, + {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b"}, + {file = "multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d"}, + {file = "multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f"}, + {file = "multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5"}, + {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581"}, + {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a"}, + {file = "multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d"}, + {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9"}, + {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2"}, + {file = "multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7"}, + {file = "multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5"}, + {file = "multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2"}, + {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f"}, + {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358"}, + {file = "multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f"}, + {file = "multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de"}, + {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5"}, + {file = "multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0"}, + {file = "multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4"}, + {file = "multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9"}, + {file = "multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56"}, + {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "mypy" version = "1.13.0" @@ -374,45 +881,177 @@ files = [ [[package]] name = "packaging" -version = "26.0" +version = "26.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, - {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, + {file = "packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f"}, + {file = "packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de"}, ] [[package]] name = "pluggy" -version = "1.5.0" +version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "propcache" +version = "0.4.1" +description = "Accelerated property cache" +optional = true +python-versions = ">=3.9" +files = [ + {file = "propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db"}, + {file = "propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8"}, + {file = "propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925"}, + {file = "propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21"}, + {file = "propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5"}, + {file = "propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db"}, + {file = "propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7"}, + {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4"}, + {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60"}, + {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f"}, + {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900"}, + {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c"}, + {file = "propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb"}, + {file = "propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37"}, + {file = "propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f"}, + {file = "propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1"}, + {file = "propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6"}, + {file = "propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75"}, + {file = "propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8"}, + {file = "propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db"}, + {file = "propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1"}, + {file = "propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf"}, + {file = "propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311"}, + {file = "propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74"}, + {file = "propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe"}, + {file = "propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af"}, + {file = "propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c"}, + {file = "propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f"}, + {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1"}, + {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24"}, + {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa"}, + {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61"}, + {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66"}, + {file = "propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81"}, + {file = "propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e"}, + {file = "propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1"}, + {file = "propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b"}, + {file = "propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566"}, + {file = "propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835"}, + {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e"}, + {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859"}, + {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b"}, + {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0"}, + {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af"}, + {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393"}, + {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874"}, + {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7"}, + {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1"}, + {file = "propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717"}, + {file = "propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37"}, + {file = "propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a"}, + {file = "propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12"}, + {file = "propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c"}, + {file = "propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded"}, + {file = "propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641"}, + {file = "propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4"}, + {file = "propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44"}, + {file = "propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d"}, + {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b"}, + {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e"}, + {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f"}, + {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49"}, + {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144"}, + {file = "propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f"}, + {file = "propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153"}, + {file = "propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992"}, + {file = "propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f"}, + {file = "propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393"}, + {file = "propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0"}, + {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a"}, + {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be"}, + {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc"}, + {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a"}, + {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89"}, + {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726"}, + {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367"}, + {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36"}, + {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455"}, + {file = "propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85"}, + {file = "propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1"}, + {file = "propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9"}, + {file = "propcache-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff"}, + {file = "propcache-0.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb"}, + {file = "propcache-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac"}, + {file = "propcache-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888"}, + {file = "propcache-0.4.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc"}, + {file = "propcache-0.4.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a"}, + {file = "propcache-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88"}, + {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00"}, + {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0"}, + {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e"}, + {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781"}, + {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183"}, + {file = "propcache-0.4.1-cp39-cp39-win32.whl", hash = "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19"}, + {file = "propcache-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f"}, + {file = "propcache-0.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938"}, + {file = "propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237"}, + {file = "propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d"}, +] [[package]] name = "pydantic" -version = "2.10.6" +version = "2.12.5" description = "Data validation using Python type hints" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, + {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, + {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" +pydantic-core = "2.41.5" +typing-extensions = ">=4.14.1" +typing-inspection = ">=0.4.2" [package.extras] email = ["email-validator (>=2.0.0)"] @@ -420,165 +1059,203 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.27.2" +version = "2.41.5" description = "Core functionality for Pydantic validation and serialization" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"}, + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, + {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] [package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +typing-extensions = ">=4.14.1" + +[[package]] +name = "pygments" +version = "2.20.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.4" +version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, + {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, ] [package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" -version = "0.23.8" +version = "1.3.0" description = "Pytest support for asyncio" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, - {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, + {file = "pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5"}, + {file = "pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5"}, ] [package.dependencies] -pytest = ">=7.0.0,<9" +backports-asyncio-runner = {version = ">=1.1,<2", markers = "python_version < \"3.11\""} +pytest = ">=8.2,<10" +typing-extensions = {version = ">=4.12", markers = "python_version < \"3.13\""} [package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-xdist" -version = "3.6.1" +version = "3.8.0" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, - {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, + {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, + {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, ] [package.dependencies] @@ -606,24 +1283,24 @@ six = ">=1.5" [[package]] name = "requests" -version = "2.32.4" +version = "2.33.1" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, + {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, + {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, ] [package.dependencies] -certifi = ">=2017.4.17" +certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "ruff" @@ -663,17 +1340,6 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - [[package]] name = "tomli" version = "2.4.1" @@ -732,24 +1398,24 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20241206" +version = "2.9.0.20260408" description = "Typing stubs for python-dateutil" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, - {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, + {file = "types_python_dateutil-2.9.0.20260408-py3-none-any.whl", hash = "sha256:473139d514a71c9d1fbd8bb328974bedcb1cc3dba57aad04ffa4157f483c216f"}, + {file = "types_python_dateutil-2.9.0.20260408.tar.gz", hash = "sha256:8b056ec01568674235f64ecbcef928972a5fac412f5aab09c516dfa2acfbb582"}, ] [[package]] name = "types-requests" -version = "2.32.0.20241016" +version = "2.33.0.20260408" description = "Typing stubs for requests" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, - {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, + {file = "types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f"}, + {file = "types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b"}, ] [package.dependencies] @@ -757,128 +1423,262 @@ urllib3 = ">=2" [[package]] name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +files = [ + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, + {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, + {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] +[package.dependencies] +typing-extensions = ">=4.12.0" + [[package]] name = "urllib3" -version = "2.2.3" +version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, + {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, + {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0)"] [[package]] name = "websockets" -version = "13.1" +version = "16.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" +files = [ + {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, + {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, + {file = "websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957"}, + {file = "websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72"}, + {file = "websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde"}, + {file = "websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3"}, + {file = "websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3"}, + {file = "websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9"}, + {file = "websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35"}, + {file = "websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8"}, + {file = "websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad"}, + {file = "websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d"}, + {file = "websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe"}, + {file = "websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b"}, + {file = "websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5"}, + {file = "websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64"}, + {file = "websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6"}, + {file = "websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac"}, + {file = "websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00"}, + {file = "websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79"}, + {file = "websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39"}, + {file = "websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c"}, + {file = "websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f"}, + {file = "websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1"}, + {file = "websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2"}, + {file = "websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89"}, + {file = "websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea"}, + {file = "websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9"}, + {file = "websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230"}, + {file = "websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c"}, + {file = "websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5"}, + {file = "websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82"}, + {file = "websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8"}, + {file = "websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f"}, + {file = "websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a"}, + {file = "websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156"}, + {file = "websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0"}, + {file = "websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904"}, + {file = "websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4"}, + {file = "websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e"}, + {file = "websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4"}, + {file = "websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1"}, + {file = "websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3"}, + {file = "websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8"}, + {file = "websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d"}, + {file = "websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244"}, + {file = "websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e"}, + {file = "websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641"}, + {file = "websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8"}, + {file = "websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e"}, + {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944"}, + {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206"}, + {file = "websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6"}, + {file = "websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd"}, + {file = "websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d"}, + {file = "websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03"}, + {file = "websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da"}, + {file = "websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c"}, + {file = "websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767"}, + {file = "websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec"}, + {file = "websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5"}, +] + +[[package]] +name = "yarl" +version = "1.23.0" +description = "Yet another URL library" +optional = true +python-versions = ">=3.10" files = [ - {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, - {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, - {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, - {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, - {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, - {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, - {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, - {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, - {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, - {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, - {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, - {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, - {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, - {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, - {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, - {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, - {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, - {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, - {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, - {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, - {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, - {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, - {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, - {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, - {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, - {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, - {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, - {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, - {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, - {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, - {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, - {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, - {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, - {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, - {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, - {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, - {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, - {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, - {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, - {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, - {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, - {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, - {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, - {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, - {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, - {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, - {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, - {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, - {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, - {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, - {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, - {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, - {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, - {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, - {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, - {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, - {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, - {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, - {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, - {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, - {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, - {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, - {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, - {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, - {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, - {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, - {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, - {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, - {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, - {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"}, - {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"}, - {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"}, - {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"}, - {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"}, - {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"}, - {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"}, - {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"}, - {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"}, - {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"}, - {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"}, - {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"}, - {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"}, - {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"}, - {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"}, - {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"}, - {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"}, + {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107"}, + {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d"}, + {file = "yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4"}, + {file = "yarl-1.23.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750"}, + {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6"}, + {file = "yarl-1.23.0-cp310-cp310-win32.whl", hash = "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d"}, + {file = "yarl-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb"}, + {file = "yarl-1.23.0-cp310-cp310-win_arm64.whl", hash = "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220"}, + {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99"}, + {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c"}, + {file = "yarl-1.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598"}, + {file = "yarl-1.23.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc"}, + {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2"}, + {file = "yarl-1.23.0-cp311-cp311-win32.whl", hash = "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5"}, + {file = "yarl-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46"}, + {file = "yarl-1.23.0-cp311-cp311-win_arm64.whl", hash = "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928"}, + {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860"}, + {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069"}, + {file = "yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51"}, + {file = "yarl-1.23.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86"}, + {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34"}, + {file = "yarl-1.23.0-cp312-cp312-win32.whl", hash = "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d"}, + {file = "yarl-1.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e"}, + {file = "yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9"}, + {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e"}, + {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5"}, + {file = "yarl-1.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4"}, + {file = "yarl-1.23.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a"}, + {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543"}, + {file = "yarl-1.23.0-cp313-cp313-win32.whl", hash = "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957"}, + {file = "yarl-1.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3"}, + {file = "yarl-1.23.0-cp313-cp313-win_arm64.whl", hash = "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3"}, + {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa"}, + {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120"}, + {file = "yarl-1.23.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9"}, + {file = "yarl-1.23.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6"}, + {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5"}, + {file = "yarl-1.23.0-cp313-cp313t-win32.whl", hash = "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595"}, + {file = "yarl-1.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090"}, + {file = "yarl-1.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144"}, + {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912"}, + {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474"}, + {file = "yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52"}, + {file = "yarl-1.23.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6"}, + {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe"}, + {file = "yarl-1.23.0-cp314-cp314-win32.whl", hash = "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169"}, + {file = "yarl-1.23.0-cp314-cp314-win_amd64.whl", hash = "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70"}, + {file = "yarl-1.23.0-cp314-cp314-win_arm64.whl", hash = "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e"}, + {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679"}, + {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412"}, + {file = "yarl-1.23.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6"}, + {file = "yarl-1.23.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2"}, + {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4"}, + {file = "yarl-1.23.0-cp314-cp314t-win32.whl", hash = "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4"}, + {file = "yarl-1.23.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2"}, + {file = "yarl-1.23.0-cp314-cp314t-win_arm64.whl", hash = "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25"}, + {file = "yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f"}, + {file = "yarl-1.23.0.tar.gz", hash = "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5"}, ] +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +propcache = ">=0.2.1" + +[extras] +aiohttp = ["aiohttp", "httpx-aiohttp"] + [metadata] lock-version = "2.0" -python-versions = "^3.8" -content-hash = "f0ca4e1b4e25a2c0c414483a6ee1a2d19c97ee1fc920fd71b264efaa4d3ad99b" +python-versions = "^3.10" +content-hash = "dd099e9cb03874e4a2fecf5b883fca8ac95981d50355ce3e88fa1f46d8e33b35" diff --git a/pyproject.toml b/pyproject.toml index d5a47bea..b12af01f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,8 +14,6 @@ classifiers = [ "Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -39,27 +37,33 @@ packages = [ Repository = 'https://github.com/deepgram/deepgram-python-sdk' [tool.poetry.dependencies] -python = "^3.8" +python = "^3.10" +aiohttp = { version = ">=3.13.4,<4", optional = true, python = ">=3.9"} httpx = ">=0.21.2" +httpx-aiohttp = { version = "0.1.8", optional = true, python = ">=3.9"} pydantic = ">= 1.9.2" -pydantic-core = ">=2.18.2" +pydantic-core = ">=2.18.2,<2.44.0" typing_extensions = ">= 4.0.0" websockets = ">=12.0" [tool.poetry.group.dev.dependencies] mypy = "==1.13.0" -pytest = "^7.4.0" -pytest-asyncio = "^0.23.5" +pytest = "^9.0.3" +pytest-asyncio = "^1.0.0" pytest-xdist = "^3.6.1" python-dateutil = "^2.9.0" types-python-dateutil = "^2.9.0.20240316" -requests = "^2.31.0" -types-requests = "^2.31.0" +urllib3 = ">=1.26.19,<2.0.0 || >=2.2.2,<3.0.0" +requests = "^2.33.0" +types-requests = "^2.33.0" ruff = "==0.11.5" [tool.pytest.ini_options] testpaths = [ "tests" ] asyncio_mode = "auto" +markers = [ + "aiohttp: tests that require httpx_aiohttp to be installed", +] [tool.mypy] plugins = ["pydantic.mypy"] @@ -91,3 +95,6 @@ section-order = ["future", "standard-library", "third-party", "first-party"] [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.extras] +aiohttp=["aiohttp", "httpx-aiohttp"] diff --git a/requirements.txt b/requirements.txt index 4c0f6431..f2579c2a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ httpx>=0.21.2 pydantic>= 1.9.2 -pydantic-core>=2.18.2 +pydantic-core>=2.18.2,<2.44.0 typing_extensions>= 4.0.0 websockets>=12.0 diff --git a/src/deepgram/__init__.py b/src/deepgram/__init__.py index 63bf6069..dd6cdb38 100644 --- a/src/deepgram/__init__.py +++ b/src/deepgram/__init__.py @@ -237,6 +237,7 @@ ) from .errors import BadRequestError from . import agent, auth, listen, manage, read, self_hosted, speak, voice_agent + from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient from .client import AsyncDeepgramClient, DeepgramClient from .environment import DeepgramClientEnvironment from .requests import ( @@ -477,6 +478,8 @@ "DeepgramClientEnvironment": ".environment", "DeepgramParams": ".requests", "DeepgramSpeakProviderModel": ".types", + "DefaultAioHttpClient": "._default_clients", + "DefaultAsyncHttpxClient": "._default_clients", "DeleteAgentConfigurationV1Response": ".types", "DeleteAgentVariableV1Response": ".types", "DeleteProjectInviteV1Response": ".types", @@ -906,6 +909,8 @@ def __dir__(): "DeepgramClientEnvironment", "DeepgramParams", "DeepgramSpeakProviderModel", + "DefaultAioHttpClient", + "DefaultAsyncHttpxClient", "DeleteAgentConfigurationV1Response", "DeleteAgentVariableV1Response", "DeleteProjectInviteV1Response", diff --git a/src/deepgram/_default_clients.py b/src/deepgram/_default_clients.py new file mode 100644 index 00000000..806dd31c --- /dev/null +++ b/src/deepgram/_default_clients.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx + +SDK_DEFAULT_TIMEOUT = 60 + +try: + import httpx_aiohttp # type: ignore[import-not-found] +except ImportError: + + class DefaultAioHttpClient(httpx.AsyncClient): # type: ignore + def __init__(self, **kwargs: typing.Any) -> None: + raise RuntimeError( + "To use the aiohttp client, install the aiohttp extra: pip install deepgram-sdk[aiohttp]" + ) + +else: + + class DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore + def __init__(self, **kwargs: typing.Any) -> None: + kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) + + +class DefaultAsyncHttpxClient(httpx.AsyncClient): + def __init__(self, **kwargs: typing.Any) -> None: + kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) diff --git a/src/deepgram/agent/v1/requests/agent_v1settings_audio_input.py b/src/deepgram/agent/v1/requests/agent_v1settings_audio_input.py index 91931180..aa68bc98 100644 --- a/src/deepgram/agent/v1/requests/agent_v1settings_audio_input.py +++ b/src/deepgram/agent/v1/requests/agent_v1settings_audio_input.py @@ -14,7 +14,7 @@ class AgentV1SettingsAudioInputParams(typing_extensions.TypedDict): Audio encoding format """ - sample_rate: float + sample_rate: int """ Sample rate in Hz. Common values are 16000, 24000, 44100, 48000 """ diff --git a/src/deepgram/agent/v1/requests/agent_v1settings_audio_output.py b/src/deepgram/agent/v1/requests/agent_v1settings_audio_output.py index 32273699..1d4ceb01 100644 --- a/src/deepgram/agent/v1/requests/agent_v1settings_audio_output.py +++ b/src/deepgram/agent/v1/requests/agent_v1settings_audio_output.py @@ -14,12 +14,12 @@ class AgentV1SettingsAudioOutputParams(typing_extensions.TypedDict): Audio encoding format for streaming TTS output """ - sample_rate: typing_extensions.NotRequired[float] + sample_rate: typing_extensions.NotRequired[int] """ Sample rate in Hz """ - bitrate: typing_extensions.NotRequired[float] + bitrate: typing_extensions.NotRequired[int] """ Audio bitrate in bits per second """ 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 968ef5cf..1e779edb 100644 --- a/src/deepgram/agent/v1/settings/think/models/raw_client.py +++ b/src/deepgram/agent/v1/settings/think/models/raw_client.py @@ -6,10 +6,12 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawModelsClient: @@ -34,7 +36,7 @@ def list( """ _response = self._client_wrapper.httpx_client.request( "v1/agent/settings/think/models", - base_url=self._client_wrapper.get_environment().base, + base_url=self._client_wrapper.get_environment().agent, method="GET", request_options=request_options, ) @@ -62,6 +64,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -87,7 +93,7 @@ async def list( """ _response = await self._client_wrapper.httpx_client.request( "v1/agent/settings/think/models", - base_url=self._client_wrapper.get_environment().base, + base_url=self._client_wrapper.get_environment().agent, method="GET", request_options=request_options, ) @@ -115,4 +121,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index 21b30ec1..e89615cb 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -3,7 +3,9 @@ import json import logging 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.unchecked_base_model import construct_type @@ -37,26 +39,6 @@ from websockets import WebSocketClientProtocol # type: ignore _logger = logging.getLogger(__name__) - - -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, @@ -120,7 +102,7 @@ async def start_listening(self): ) continue 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) @@ -160,12 +142,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(type="KeepAlive")) + await self._send_model(message) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -214,7 +196,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): @@ -260,7 +242,7 @@ def start_listening(self): ) continue 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) @@ -300,12 +282,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(type="KeepAlive")) + self._send_model(message) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -354,4 +336,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/agent/v1/types/agent_v1settings_audio_input.py b/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py index 59eeb7dd..38f1b0fc 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_audio_input.py @@ -18,7 +18,7 @@ class AgentV1SettingsAudioInput(UncheckedBaseModel): Audio encoding format """ - sample_rate: float = pydantic.Field() + sample_rate: int = pydantic.Field() """ Sample rate in Hz. Common values are 16000, 24000, 44100, 48000 """ 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 88c9a109..bfc06608 100644 --- a/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py +++ b/src/deepgram/agent/v1/types/agent_v1settings_audio_output.py @@ -18,12 +18,12 @@ class AgentV1SettingsAudioOutput(UncheckedBaseModel): Audio encoding format for streaming TTS output """ - sample_rate: typing.Optional[float] = pydantic.Field(default=None) + sample_rate: typing.Optional[int] = pydantic.Field(default=None) """ Sample rate in Hz """ - bitrate: typing.Optional[float] = pydantic.Field(default=None) + bitrate: typing.Optional[int] = pydantic.Field(default=None) """ Audio bitrate in bits per second """ diff --git a/src/deepgram/auth/v1/tokens/raw_client.py b/src/deepgram/auth/v1/tokens/raw_client.py index c2a652a4..2492396d 100644 --- a/src/deepgram/auth/v1/tokens/raw_client.py +++ b/src/deepgram/auth/v1/tokens/raw_client.py @@ -6,10 +6,12 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse +from ....core.parse_error import ParsingError 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 +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -75,6 +77,10 @@ def grant( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -138,4 +144,8 @@ async def grant( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/base_client.py b/src/deepgram/base_client.py index e39417ff..12045fe0 100644 --- a/src/deepgram/base_client.py +++ b/src/deepgram/base_client.py @@ -166,6 +166,24 @@ def voice_agent(self): return self._voice_agent +def _make_default_async_client( + timeout: typing.Optional[float], + follow_redirects: typing.Optional[bool], +) -> httpx.AsyncClient: + try: + import httpx_aiohttp # type: ignore[import-not-found] + except ImportError: + pass + else: + if follow_redirects is not None: + return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout, follow_redirects=follow_redirects) + return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout) + + if follow_redirects is not None: + return httpx.AsyncClient(timeout=timeout, follow_redirects=follow_redirects) + return httpx.AsyncClient(timeout=timeout) + + class AsyncBaseClient: """ Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. @@ -230,9 +248,7 @@ def __init__( headers=headers, httpx_client=httpx_client if httpx_client is not None - else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) - if follow_redirects is not None - else httpx.AsyncClient(timeout=_defaulted_timeout), + else _make_default_async_client(timeout=_defaulted_timeout, follow_redirects=follow_redirects), timeout=_defaulted_timeout, logging=logging, ) diff --git a/src/deepgram/core/__init__.py b/src/deepgram/core/__init__.py index d247a71c..9e2545ad 100644 --- a/src/deepgram/core/__init__.py +++ b/src/deepgram/core/__init__.py @@ -13,8 +13,9 @@ from .file import File, convert_file_dict_to_httpx_tuples, with_content_type from .http_client import AsyncHttpClient, HttpClient from .http_response import AsyncHttpResponse, HttpResponse - from .jsonable_encoder import jsonable_encoder + from .jsonable_encoder import encode_path_param, jsonable_encoder from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger + from .parse_error import ParsingError from .pydantic_utilities import ( IS_PYDANTIC_V2, UniversalBaseModel, @@ -49,6 +50,7 @@ "LogConfig": ".logging", "LogLevel": ".logging", "Logger": ".logging", + "ParsingError": ".parse_error", "RequestOptions": ".request_options", "Rfc2822DateTime": ".datetime_utils", "SyncClientWrapper": ".client_wrapper", @@ -60,6 +62,7 @@ "convert_and_respect_annotation_metadata": ".serialization", "convert_file_dict_to_httpx_tuples": ".file", "create_logger": ".logging", + "encode_path_param": ".jsonable_encoder", "encode_query": ".query_encoder", "get_status_code": ".websocket_compat", "jsonable_encoder": ".jsonable_encoder", @@ -114,6 +117,7 @@ def __dir__(): "LogConfig", "LogLevel", "Logger", + "ParsingError", "RequestOptions", "Rfc2822DateTime", "SyncClientWrapper", @@ -125,6 +129,7 @@ def __dir__(): "convert_and_respect_annotation_metadata", "convert_file_dict_to_httpx_tuples", "create_logger", + "encode_path_param", "encode_query", "get_status_code", "jsonable_encoder", diff --git a/src/deepgram/core/http_client.py b/src/deepgram/core/http_client.py index ee937589..f0a39ca8 100644 --- a/src/deepgram/core/http_client.py +++ b/src/deepgram/core/http_client.py @@ -118,6 +118,12 @@ def _retry_timeout(response: httpx.Response, retries: int) -> float: return _add_symmetric_jitter(backoff) +def _retry_timeout_from_retries(retries: int) -> float: + """Determine retry timeout using exponential backoff when no response is available.""" + backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + return _add_symmetric_jitter(backoff) + + def _should_retry(response: httpx.Response) -> bool: retryable_400s = [429, 408, 409] return response.status_code >= 500 or response.status_code in retryable_400s @@ -265,11 +271,13 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + base_max_retries: int = 2, logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers + self.base_max_retries = base_max_retries self.httpx_client = httpx_client self.logger = create_logger(logging_config) @@ -364,19 +372,44 @@ def request( has_body=json_body is not None or data_body is not None, ) - response = self.httpx_client.request( - method=method, - url=_request_url, - headers=_request_headers, - params=_encoded_params if _encoded_params else None, - json=json_body, - data=data_body, - content=content, - files=request_files, - timeout=timeout, + max_retries: int = ( + request_options.get("max_retries", self.base_max_retries) + if request_options is not None + else self.base_max_retries ) - max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 + try: + response = self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + except (httpx.ConnectError, httpx.RemoteProtocolError): + if retries < max_retries: + time.sleep(_retry_timeout_from_retries(retries=retries)) + return self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + data=data, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + force_multipart=force_multipart, + ) + raise + if _should_retry(response=response): if retries < max_retries: time.sleep(_retry_timeout(response=response, retries=retries)) @@ -386,12 +419,14 @@ def request( base_url=base_url, params=params, json=json, + data=data, content=content, files=files, headers=headers, request_options=request_options, retries=retries + 1, omit=omit, + force_multipart=force_multipart, ) if self.logger.is_debug(): @@ -518,12 +553,14 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + base_max_retries: int = 2, async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None, logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers + self.base_max_retries = base_max_retries self.async_base_headers = async_base_headers self.httpx_client = httpx_client self.logger = create_logger(logging_config) @@ -627,19 +664,44 @@ async def request( has_body=json_body is not None or data_body is not None, ) - response = await self.httpx_client.request( - method=method, - url=_request_url, - headers=_request_headers, - params=_encoded_params if _encoded_params else None, - json=json_body, - data=data_body, - content=content, - files=request_files, - timeout=timeout, + max_retries: int = ( + request_options.get("max_retries", self.base_max_retries) + if request_options is not None + else self.base_max_retries ) - max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 + try: + response = await self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + except (httpx.ConnectError, httpx.RemoteProtocolError): + if retries < max_retries: + await asyncio.sleep(_retry_timeout_from_retries(retries=retries)) + return await self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + data=data, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + force_multipart=force_multipart, + ) + raise + if _should_retry(response=response): if retries < max_retries: await asyncio.sleep(_retry_timeout(response=response, retries=retries)) @@ -649,12 +711,14 @@ async def request( base_url=base_url, params=params, json=json, + data=data, content=content, files=files, headers=headers, request_options=request_options, retries=retries + 1, omit=omit, + force_multipart=force_multipart, ) if self.logger.is_debug(): diff --git a/src/deepgram/core/jsonable_encoder.py b/src/deepgram/core/jsonable_encoder.py index f8beaeaf..5b0902eb 100644 --- a/src/deepgram/core/jsonable_encoder.py +++ b/src/deepgram/core/jsonable_encoder.py @@ -106,3 +106,15 @@ def fallback_serializer(o: Any) -> Any: return jsonable_encoder(data, custom_encoder=custom_encoder) return to_jsonable_with_fallback(obj, fallback_serializer) + + +def encode_path_param(obj: Any) -> str: + """Encode a value for use in a URL path segment. + + Ensures proper string conversion for all types, including + booleans which need lowercase 'true'/'false' rather than + Python's 'True'/'False'. + """ + if isinstance(obj, bool): + return "true" if obj else "false" + return str(jsonable_encoder(obj)) diff --git a/src/deepgram/core/parse_error.py b/src/deepgram/core/parse_error.py new file mode 100644 index 00000000..4527c6a8 --- /dev/null +++ b/src/deepgram/core/parse_error.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +class ParsingError(Exception): + """ + Raised when the SDK fails to parse/validate a response from the server. + This typically indicates that the server returned a response whose shape + does not match the expected schema. + """ + + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any + cause: Optional[Exception] + + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + cause: Optional[Exception] = None, + ) -> None: + self.headers = headers + self.status_code = status_code + self.body = body + self.cause = cause + super().__init__() + if cause is not None: + self.__cause__ = cause + + def __str__(self) -> str: + cause_str = f", cause: {self.cause}" if self.cause is not None else "" + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}{cause_str}" diff --git a/src/deepgram/core/pydantic_utilities.py b/src/deepgram/core/pydantic_utilities.py index 831aadc3..fea3a08d 100644 --- a/src/deepgram/core/pydantic_utilities.py +++ b/src/deepgram/core/pydantic_utilities.py @@ -26,6 +26,7 @@ import pydantic import typing_extensions +from pydantic.fields import FieldInfo as _FieldInfo _logger = logging.getLogger(__name__) @@ -35,8 +36,6 @@ IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") if IS_PYDANTIC_V2: - import warnings - _datetime_adapter = pydantic.TypeAdapter(dt.datetime) # type: ignore[attr-defined] _date_adapter = pydantic.TypeAdapter(dt.date) # type: ignore[attr-defined] @@ -52,22 +51,80 @@ def parse_date(value: Any) -> dt.date: # type: ignore[misc] return value return _date_adapter.validate_python(value) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - from pydantic.v1.fields import ModelField as ModelField - from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] - from pydantic.v1.typing import get_args as get_args - from pydantic.v1.typing import get_origin as get_origin - from pydantic.v1.typing import is_literal_type as is_literal_type - from pydantic.v1.typing import is_union as is_union + # Avoid importing from pydantic.v1 to maintain Python 3.14 compatibility. + from typing import get_args as get_args # type: ignore[assignment] + from typing import get_origin as get_origin # type: ignore[assignment] + + def is_literal_type(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc] + return typing_extensions.get_origin(tp) is typing_extensions.Literal + + def is_union(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc] + return tp is Union or typing_extensions.get_origin(tp) is Union # type: ignore[comparison-overlap] + + # Inline encoders_by_type to avoid importing from pydantic.v1.json + import re as _re + from collections import deque as _deque + from decimal import Decimal as _Decimal + from enum import Enum as _Enum + from ipaddress import ( + IPv4Address as _IPv4Address, + ) + from ipaddress import ( + IPv4Interface as _IPv4Interface, + ) + from ipaddress import ( + IPv4Network as _IPv4Network, + ) + from ipaddress import ( + IPv6Address as _IPv6Address, + ) + from ipaddress import ( + IPv6Interface as _IPv6Interface, + ) + from ipaddress import ( + IPv6Network as _IPv6Network, + ) + from pathlib import Path as _Path + from types import GeneratorType as _GeneratorType + from uuid import UUID as _UUID + + from pydantic.fields import FieldInfo as ModelField # type: ignore[no-redef, assignment] + + def _decimal_encoder(dec_value: Any) -> Any: + if dec_value.as_tuple().exponent >= 0: + return int(dec_value) + return float(dec_value) + + encoders_by_type: Dict[Type[Any], Callable[[Any], Any]] = { # type: ignore[no-redef] + bytes: lambda o: o.decode(), + dt.date: lambda o: o.isoformat(), + dt.datetime: lambda o: o.isoformat(), + dt.time: lambda o: o.isoformat(), + dt.timedelta: lambda td: td.total_seconds(), + _Decimal: _decimal_encoder, + _Enum: lambda o: o.value, + frozenset: list, + _deque: list, + _GeneratorType: list, + _IPv4Address: str, + _IPv4Interface: str, + _IPv4Network: str, + _IPv6Address: str, + _IPv6Interface: str, + _IPv6Network: str, + _Path: str, + _re.Pattern: lambda o: o.pattern, + set: list, + _UUID: str, + } else: from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] - from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef, assignment] from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] from pydantic.typing import get_args as get_args # type: ignore[no-redef] from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] - from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef, assignment] from pydantic.typing import is_union as is_union # type: ignore[no-redef] from .datetime_utils import serialize_datetime @@ -554,7 +611,7 @@ def decorator(func: AnyCallable) -> AnyCallable: return decorator -PydanticField = Union[ModelField, pydantic.fields.FieldInfo] +PydanticField = Union[ModelField, _FieldInfo] def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: diff --git a/src/deepgram/core/unchecked_base_model.py b/src/deepgram/core/unchecked_base_model.py index 9ea71ca6..67d7e3be 100644 --- a/src/deepgram/core/unchecked_base_model.py +++ b/src/deepgram/core/unchecked_base_model.py @@ -1,13 +1,15 @@ # This file was auto-generated by Fern from our API Definition. import datetime as dt +import enum import inspect +import sys import typing import uuid import pydantic import typing_extensions -from .pydantic_utilities import ( +from .pydantic_utilities import ( # type: ignore[attr-defined] IS_PYDANTIC_V2, ModelField, UniversalBaseModel, @@ -33,6 +35,28 @@ def __init__(self, *, discriminant: str) -> None: Model = typing.TypeVar("Model", bound=pydantic.BaseModel) +def _maybe_resolve_forward_ref( + type_: typing.Any, + host: typing.Optional[typing.Type[typing.Any]], +) -> typing.Any: + """Resolve a ForwardRef using the module where *host* is defined. + + Pydantic v2 + ``from __future__ import annotations`` can leave field + annotations as ``list[ForwardRef('Block')]`` even after ``model_rebuild``. + Without resolution, ``construct_type`` sees a ForwardRef (not a class) and + skips recursive model construction, leaving nested data as raw dicts. + """ + if host is None or not isinstance(type_, typing.ForwardRef): + return type_ + mod = sys.modules.get(host.__module__) + if mod is None: + return type_ + try: + return eval(type_.__forward_arg__, vars(mod)) + except Exception: + return type_ + + class UncheckedBaseModel(UniversalBaseModel): if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow") # type: ignore # Pydantic v2 @@ -86,7 +110,7 @@ def construct( 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] + construct_type(object_=values[key], type_=type_, host=cls) if type_ is not None else values[key] ) _fields_set.add(name) else: @@ -150,15 +174,75 @@ def _validate_collection_items_compatible(collection: typing.Any, target_type: t return True -def _convert_undiscriminated_union_type(union_type: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: +def _get_literal_field_value( + inner_type: typing.Type[typing.Any], field_name: str, field: typing.Any, object_: typing.Any +) -> typing.Any: + """Get the value of a Literal field from *object_*, checking both alias and field name.""" + name_or_alias = get_field_to_alias_mapping(inner_type).get(field_name, field_name) + pydantic_alias = getattr(field, "alias", None) + if isinstance(object_, dict): + if name_or_alias in object_: + return object_[name_or_alias] + if pydantic_alias and pydantic_alias != name_or_alias and pydantic_alias in object_: + return object_[pydantic_alias] + return None + return getattr(object_, name_or_alias, getattr(object_, pydantic_alias, None) if pydantic_alias else None) + + +def _literal_fields_match_strict(inner_type: typing.Type[typing.Any], object_: typing.Any) -> bool: + """Return True iff every Literal-typed field in *inner_type* is **present** in + *object_* and its value equals the field's declared default. + + This prevents models whose fields are all optional (e.g. ``FigureDetails``) + from vacuously matching inputs that don't carry the discriminant key at all + (e.g. ``{}`` for text blocks). For types with no Literal fields this + returns True unconditionally. + """ + fields = _get_model_fields(inner_type) + for field_name, field in fields.items(): + 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) + object_value = _get_literal_field_value(inner_type, field_name, field, object_) + if field_default != object_value: + return False + return True + + +def _convert_undiscriminated_union_type( + union_type: typing.Type[typing.Any], + object_: typing.Any, + host: typing.Optional[typing.Type[typing.Any]] = None, +) -> typing.Any: inner_types = get_args(union_type) if typing.Any in inner_types: return object_ + # When any union member carries a Literal discriminant field, require the + # discriminant key to be present AND matching before accepting a candidate. + # This prevents models with all-optional fields (e.g. FigureDetails) from + # greedily matching inputs that belong to a different variant or to a + # plain-dict fallback (e.g. EmptyBlockDetails = Dict[str, Any]). + has_literal_discriminant = any( + inspect.isclass(t) + and issubclass(t, pydantic.BaseModel) + and any( + is_literal_type( + f.annotation if IS_PYDANTIC_V2 else f.outer_type_ # type: ignore + ) + for f in _get_model_fields(t).values() + ) + for t in inner_types + ) + 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] + list_inner_type = _maybe_resolve_forward_ref(get_args(inner_type)[0], host) 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 @@ -170,55 +254,63 @@ def _convert_undiscriminated_union_type(union_type: typing.Type[typing.Any], obj try: if inspect.isclass(inner_type) and issubclass(inner_type, pydantic.BaseModel): + if has_literal_discriminant and not _literal_fields_match_strict(inner_type, object_): + continue # 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 + # 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) + if has_literal_discriminant: + if not _literal_fields_match_strict(inner_type, object_): + continue + else: + # Legacy lenient check: skip only when a Literal value is + # present but doesn't match (allows absent-discriminant inputs). + fields = _get_model_fields(inner_type) + literal_fields_match = True + for field_name, field in fields.items(): + if IS_PYDANTIC_V2: + field_type = field.annotation # type: ignore # Pydantic v2 else: - object_value = getattr(object_, name_or_alias, None) + field_type = field.outer_type_ # type: ignore # Pydantic v1 - # 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 is_literal_type(field_type): # type: ignore[arg-type] + field_default = _get_field_default(field) + object_value = _get_literal_field_value(inner_type, field_name, field, object_) + 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: + if not literal_fields_match: continue - # Second pass: if no literal matches, just return the first successful cast + try: + return construct_type(object_=object_, type_=inner_type, host=host) + except Exception: + continue + + # Second pass: if no literal matches, return the first successful cast. + # When a Literal discriminant is present, skip Pydantic models whose + # discriminant doesn't match so that plain-dict fallback types are reached. for inner_type in inner_types: try: - return construct_type(object_=object_, type_=inner_type) + if has_literal_discriminant and inspect.isclass(inner_type) and issubclass(inner_type, pydantic.BaseModel): + if not _literal_fields_match_strict(inner_type, object_): + continue + return construct_type(object_=object_, type_=inner_type, host=host) except Exception: continue -def _convert_union_type(type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: +def _convert_union_type( + type_: typing.Type[typing.Any], + object_: typing.Any, + host: typing.Optional[typing.Type[typing.Any]] = None, +) -> typing.Any: base_type = get_origin(type_) or type_ union_type = type_ if base_type == typing_extensions.Annotated: # type: ignore[comparison-overlap] @@ -234,14 +326,19 @@ def _convert_union_type(type_: typing.Type[typing.Any], object_: typing.Any) -> except: objects_discriminant = object_[metadata.discriminant] if inner_type.__fields__[metadata.discriminant].default == objects_discriminant: - return construct_type(object_=object_, type_=inner_type) + return construct_type(object_=object_, type_=inner_type, host=host) except Exception: # Allow to fall through to our regular union handling pass - return _convert_undiscriminated_union_type(union_type, object_) + return _convert_undiscriminated_union_type(union_type, object_, host) -def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any: +def construct_type( + *, + type_: typing.Type[typing.Any], + object_: typing.Any, + host: typing.Optional[typing.Type[typing.Any]] = None, +) -> typing.Any: """ Here we are essentially creating the same `construct` method in spirit as the above, but for all types, not just Pydantic models. @@ -264,8 +361,12 @@ def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> ty return object_ key_type, items_type = get_args(type_) + key_type = _maybe_resolve_forward_ref(key_type, host) + items_type = _maybe_resolve_forward_ref(items_type, host) d = { - construct_type(object_=key, type_=key_type): construct_type(object_=item, type_=items_type) + construct_type(object_=key, type_=key_type, host=host): construct_type( + object_=item, type_=items_type, host=host + ) for key, item in object_.items() } return d @@ -274,18 +375,18 @@ def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> ty 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_] + inner_type = _maybe_resolve_forward_ref(get_args(type_)[0], host) + return [construct_type(object_=entry, type_=inner_type, host=host) 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_} + inner_type = _maybe_resolve_forward_ref(get_args(type_)[0], host) + return {construct_type(object_=entry, type_=inner_type, host=host) for entry in object_} if is_union(base_type) or is_annotated_union: - return _convert_union_type(type_, object_) + return _convert_union_type(type_, object_, host) # Cannot do an `issubclass` with a literal type, let's also just confirm we have a class before this call if ( @@ -339,6 +440,12 @@ def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> ty except Exception: return object_ + if inspect.isclass(base_type) and issubclass(base_type, enum.Enum): + try: + return base_type(object_) + except (ValueError, KeyError): + return object_ + return object_ @@ -348,7 +455,9 @@ def _get_is_populate_by_name(model: typing.Type["Model"]) -> bool: return model.__config__.allow_population_by_field_name # type: ignore # Pydantic v1 -PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo] +from pydantic.fields import FieldInfo as _FieldInfo + +PydanticField = typing.Union[ModelField, _FieldInfo] # Pydantic V1 swapped the typing of __fields__'s values from ModelField to FieldInfo diff --git a/src/deepgram/environment.py b/src/deepgram/environment.py index e514ef69..bbbe3e0a 100644 --- a/src/deepgram/environment.py +++ b/src/deepgram/environment.py @@ -5,7 +5,6 @@ class DeepgramClientEnvironment: PRODUCTION: DeepgramClientEnvironment - AGENT: DeepgramClientEnvironment def __init__(self, *, base: str, agent: str, production: str): self.base = base @@ -16,6 +15,3 @@ def __init__(self, *, base: str, agent: str, production: str): DeepgramClientEnvironment.PRODUCTION = DeepgramClientEnvironment( base="https://api.deepgram.com", agent="wss://agent.deepgram.com", production="wss://api.deepgram.com" ) -DeepgramClientEnvironment.AGENT = DeepgramClientEnvironment( - base="https://agent.deepgram.com", agent="wss://agent.deepgram.com", production="wss://api.deepgram.com" -) diff --git a/src/deepgram/listen/__init__.py b/src/deepgram/listen/__init__.py index 1240afba..6a178489 100644 --- a/src/deepgram/listen/__init__.py +++ b/src/deepgram/listen/__init__.py @@ -42,8 +42,16 @@ ListenV2CloseStream, ListenV2CloseStreamParams, ListenV2CloseStreamType, + ListenV2Configure, ListenV2ConfigureFailure, ListenV2ConfigureFailureParams, + ListenV2ConfigureParams, + ListenV2ConfigureSuccess, + ListenV2ConfigureSuccessParams, + ListenV2ConfigureSuccessThresholds, + ListenV2ConfigureSuccessThresholdsParams, + ListenV2ConfigureThresholds, + ListenV2ConfigureThresholdsParams, ListenV2Connected, ListenV2ConnectedParams, ListenV2FatalError, @@ -87,8 +95,16 @@ "ListenV2CloseStream": ".v2", "ListenV2CloseStreamParams": ".v2", "ListenV2CloseStreamType": ".v2", + "ListenV2Configure": ".v2", "ListenV2ConfigureFailure": ".v2", "ListenV2ConfigureFailureParams": ".v2", + "ListenV2ConfigureParams": ".v2", + "ListenV2ConfigureSuccess": ".v2", + "ListenV2ConfigureSuccessParams": ".v2", + "ListenV2ConfigureSuccessThresholds": ".v2", + "ListenV2ConfigureSuccessThresholdsParams": ".v2", + "ListenV2ConfigureThresholds": ".v2", + "ListenV2ConfigureThresholdsParams": ".v2", "ListenV2Connected": ".v2", "ListenV2ConnectedParams": ".v2", "ListenV2FatalError": ".v2", @@ -157,8 +173,16 @@ def __dir__(): "ListenV2CloseStream", "ListenV2CloseStreamParams", "ListenV2CloseStreamType", + "ListenV2Configure", "ListenV2ConfigureFailure", "ListenV2ConfigureFailureParams", + "ListenV2ConfigureParams", + "ListenV2ConfigureSuccess", + "ListenV2ConfigureSuccessParams", + "ListenV2ConfigureSuccessThresholds", + "ListenV2ConfigureSuccessThresholdsParams", + "ListenV2ConfigureThresholds", + "ListenV2ConfigureThresholdsParams", "ListenV2Connected", "ListenV2ConnectedParams", "ListenV2FatalError", diff --git a/src/deepgram/listen/v1/media/client.py b/src/deepgram/listen/v1/media/client.py index ab81ae3b..df47e724 100644 --- a/src/deepgram/listen/v1/media/client.py +++ b/src/deepgram/listen/v1/media/client.py @@ -224,6 +224,7 @@ def transcribe_url( dictation=True, encoding="linear16", filler_words=True, + keyterm=["keyterm"], keywords="keywords", language="language", measurements=True, @@ -714,6 +715,7 @@ async def main() -> None: dictation=True, encoding="linear16", filler_words=True, + keyterm=["keyterm"], keywords="keywords", language="language", measurements=True, diff --git a/src/deepgram/listen/v1/media/raw_client.py b/src/deepgram/listen/v1/media/raw_client.py index 830d4259..68860bdc 100644 --- a/src/deepgram/listen/v1/media/raw_client.py +++ b/src/deepgram/listen/v1/media/raw_client.py @@ -6,6 +6,7 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse +from ....core.parse_error import ParsingError from ....core.request_options import RequestOptions from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError @@ -17,6 +18,7 @@ from .types.media_transcribe_request_summarize import MediaTranscribeRequestSummarize from .types.media_transcribe_request_version import MediaTranscribeRequestVersion from .types.media_transcribe_response import MediaTranscribeResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -266,6 +268,10 @@ def transcribe_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def transcribe_file( @@ -506,6 +512,10 @@ def transcribe_file( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -753,6 +763,10 @@ async def transcribe_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def transcribe_file( @@ -993,4 +1007,8 @@ async def transcribe_file( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/listen/v1/requests/listen_v1metadata.py b/src/deepgram/listen/v1/requests/listen_v1metadata.py index 2b648b48..d0f2932f 100644 --- a/src/deepgram/listen/v1/requests/listen_v1metadata.py +++ b/src/deepgram/listen/v1/requests/listen_v1metadata.py @@ -36,7 +36,7 @@ class ListenV1MetadataParams(typing_extensions.TypedDict): The duration """ - channels: float + channels: int """ The channels """ diff --git a/src/deepgram/listen/v1/requests/listen_v1results.py b/src/deepgram/listen/v1/requests/listen_v1results.py index 96e152f0..39f6a972 100644 --- a/src/deepgram/listen/v1/requests/listen_v1results.py +++ b/src/deepgram/listen/v1/requests/listen_v1results.py @@ -14,7 +14,7 @@ class ListenV1ResultsParams(typing_extensions.TypedDict): Message type identifier """ - channel_index: typing.Sequence[float] + channel_index: typing.Sequence[int] """ The index of the channel """ diff --git a/src/deepgram/listen/v1/requests/listen_v1results_channel_alternatives_item_words_item.py b/src/deepgram/listen/v1/requests/listen_v1results_channel_alternatives_item_words_item.py index c28d5979..9b48906b 100644 --- a/src/deepgram/listen/v1/requests/listen_v1results_channel_alternatives_item_words_item.py +++ b/src/deepgram/listen/v1/requests/listen_v1results_channel_alternatives_item_words_item.py @@ -34,7 +34,7 @@ class ListenV1ResultsChannelAlternativesItemWordsItemParams(typing_extensions.Ty The punctuated word of the word """ - speaker: typing_extensions.NotRequired[float] + speaker: typing_extensions.NotRequired[int] """ The speaker of the word """ diff --git a/src/deepgram/listen/v1/requests/listen_v1speech_started.py b/src/deepgram/listen/v1/requests/listen_v1speech_started.py index 1cc1dcfa..da46d287 100644 --- a/src/deepgram/listen/v1/requests/listen_v1speech_started.py +++ b/src/deepgram/listen/v1/requests/listen_v1speech_started.py @@ -11,7 +11,7 @@ class ListenV1SpeechStartedParams(typing_extensions.TypedDict): Message type identifier """ - channel: typing.Sequence[float] + channel: typing.Sequence[int] """ The channel """ diff --git a/src/deepgram/listen/v1/requests/listen_v1utterance_end.py b/src/deepgram/listen/v1/requests/listen_v1utterance_end.py index 37ae57b8..2713912a 100644 --- a/src/deepgram/listen/v1/requests/listen_v1utterance_end.py +++ b/src/deepgram/listen/v1/requests/listen_v1utterance_end.py @@ -11,7 +11,7 @@ class ListenV1UtteranceEndParams(typing_extensions.TypedDict): Message type identifier """ - channel: typing.Sequence[float] + channel: typing.Sequence[int] """ The channel """ diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index 5954d116..cffa82b7 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -3,7 +3,9 @@ import json import logging 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.unchecked_base_model import construct_type @@ -67,7 +69,7 @@ async def start_listening(self): ) continue 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) @@ -79,26 +81,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: """ @@ -172,7 +174,7 @@ def start_listening(self): ) continue 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) @@ -184,26 +186,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/v1/types/listen_v1metadata.py b/src/deepgram/listen/v1/types/listen_v1metadata.py index 5a048330..eb094c3b 100644 --- a/src/deepgram/listen/v1/types/listen_v1metadata.py +++ b/src/deepgram/listen/v1/types/listen_v1metadata.py @@ -38,7 +38,7 @@ class ListenV1Metadata(UncheckedBaseModel): The duration """ - channels: float = pydantic.Field() + channels: int = pydantic.Field() """ The channels """ diff --git a/src/deepgram/listen/v1/types/listen_v1results.py b/src/deepgram/listen/v1/types/listen_v1results.py index 2ac0f05c..02250332 100644 --- a/src/deepgram/listen/v1/types/listen_v1results.py +++ b/src/deepgram/listen/v1/types/listen_v1results.py @@ -16,7 +16,7 @@ class ListenV1Results(UncheckedBaseModel): Message type identifier """ - channel_index: typing.List[float] = pydantic.Field() + channel_index: typing.List[int] = pydantic.Field() """ The index of the channel """ 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 30060dda..dd4580e1 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 @@ -38,7 +38,7 @@ class ListenV1ResultsChannelAlternativesItemWordsItem(UncheckedBaseModel): The punctuated word of the word """ - speaker: typing.Optional[float] = pydantic.Field(default=None) + speaker: typing.Optional[int] = pydantic.Field(default=None) """ The speaker of the word """ diff --git a/src/deepgram/listen/v1/types/listen_v1speech_started.py b/src/deepgram/listen/v1/types/listen_v1speech_started.py index ff986c28..43526890 100644 --- a/src/deepgram/listen/v1/types/listen_v1speech_started.py +++ b/src/deepgram/listen/v1/types/listen_v1speech_started.py @@ -13,7 +13,7 @@ class ListenV1SpeechStarted(UncheckedBaseModel): Message type identifier """ - channel: typing.List[float] = pydantic.Field() + channel: typing.List[int] = pydantic.Field() """ The channel """ diff --git a/src/deepgram/listen/v1/types/listen_v1utterance_end.py b/src/deepgram/listen/v1/types/listen_v1utterance_end.py index 893468fc..324affcd 100644 --- a/src/deepgram/listen/v1/types/listen_v1utterance_end.py +++ b/src/deepgram/listen/v1/types/listen_v1utterance_end.py @@ -13,7 +13,7 @@ class ListenV1UtteranceEnd(UncheckedBaseModel): Message type identifier """ - channel: typing.List[float] = pydantic.Field() + channel: typing.List[int] = pydantic.Field() """ The channel """ diff --git a/src/deepgram/listen/v2/__init__.py b/src/deepgram/listen/v2/__init__.py index ab491617..ca134a12 100644 --- a/src/deepgram/listen/v2/__init__.py +++ b/src/deepgram/listen/v2/__init__.py @@ -9,7 +9,11 @@ from .types import ( ListenV2CloseStream, ListenV2CloseStreamType, + ListenV2Configure, ListenV2ConfigureFailure, + ListenV2ConfigureSuccess, + ListenV2ConfigureSuccessThresholds, + ListenV2ConfigureThresholds, ListenV2Connected, ListenV2FatalError, ListenV2TurnInfo, @@ -19,6 +23,10 @@ from .requests import ( ListenV2CloseStreamParams, ListenV2ConfigureFailureParams, + ListenV2ConfigureParams, + ListenV2ConfigureSuccessParams, + ListenV2ConfigureSuccessThresholdsParams, + ListenV2ConfigureThresholdsParams, ListenV2ConnectedParams, ListenV2FatalErrorParams, ListenV2TurnInfoParams, @@ -28,8 +36,16 @@ "ListenV2CloseStream": ".types", "ListenV2CloseStreamParams": ".requests", "ListenV2CloseStreamType": ".types", + "ListenV2Configure": ".types", "ListenV2ConfigureFailure": ".types", "ListenV2ConfigureFailureParams": ".requests", + "ListenV2ConfigureParams": ".requests", + "ListenV2ConfigureSuccess": ".types", + "ListenV2ConfigureSuccessParams": ".requests", + "ListenV2ConfigureSuccessThresholds": ".types", + "ListenV2ConfigureSuccessThresholdsParams": ".requests", + "ListenV2ConfigureThresholds": ".types", + "ListenV2ConfigureThresholdsParams": ".requests", "ListenV2Connected": ".types", "ListenV2ConnectedParams": ".requests", "ListenV2FatalError": ".types", @@ -67,8 +83,16 @@ def __dir__(): "ListenV2CloseStream", "ListenV2CloseStreamParams", "ListenV2CloseStreamType", + "ListenV2Configure", "ListenV2ConfigureFailure", "ListenV2ConfigureFailureParams", + "ListenV2ConfigureParams", + "ListenV2ConfigureSuccess", + "ListenV2ConfigureSuccessParams", + "ListenV2ConfigureSuccessThresholds", + "ListenV2ConfigureSuccessThresholdsParams", + "ListenV2ConfigureThresholds", + "ListenV2ConfigureThresholdsParams", "ListenV2Connected", "ListenV2ConnectedParams", "ListenV2FatalError", diff --git a/src/deepgram/listen/v2/requests/__init__.py b/src/deepgram/listen/v2/requests/__init__.py index 49573944..84e08faa 100644 --- a/src/deepgram/listen/v2/requests/__init__.py +++ b/src/deepgram/listen/v2/requests/__init__.py @@ -7,7 +7,11 @@ if typing.TYPE_CHECKING: from .listen_v2close_stream import ListenV2CloseStreamParams + from .listen_v2configure import ListenV2ConfigureParams from .listen_v2configure_failure import ListenV2ConfigureFailureParams + from .listen_v2configure_success import ListenV2ConfigureSuccessParams + from .listen_v2configure_success_thresholds import ListenV2ConfigureSuccessThresholdsParams + from .listen_v2configure_thresholds import ListenV2ConfigureThresholdsParams from .listen_v2connected import ListenV2ConnectedParams from .listen_v2fatal_error import ListenV2FatalErrorParams from .listen_v2turn_info import ListenV2TurnInfoParams @@ -15,6 +19,10 @@ _dynamic_imports: typing.Dict[str, str] = { "ListenV2CloseStreamParams": ".listen_v2close_stream", "ListenV2ConfigureFailureParams": ".listen_v2configure_failure", + "ListenV2ConfigureParams": ".listen_v2configure", + "ListenV2ConfigureSuccessParams": ".listen_v2configure_success", + "ListenV2ConfigureSuccessThresholdsParams": ".listen_v2configure_success_thresholds", + "ListenV2ConfigureThresholdsParams": ".listen_v2configure_thresholds", "ListenV2ConnectedParams": ".listen_v2connected", "ListenV2FatalErrorParams": ".listen_v2fatal_error", "ListenV2TurnInfoParams": ".listen_v2turn_info", @@ -46,6 +54,10 @@ def __dir__(): __all__ = [ "ListenV2CloseStreamParams", "ListenV2ConfigureFailureParams", + "ListenV2ConfigureParams", + "ListenV2ConfigureSuccessParams", + "ListenV2ConfigureSuccessThresholdsParams", + "ListenV2ConfigureThresholdsParams", "ListenV2ConnectedParams", "ListenV2FatalErrorParams", "ListenV2TurnInfoParams", diff --git a/src/deepgram/listen/v2/requests/listen_v2configure.py b/src/deepgram/listen/v2/requests/listen_v2configure.py new file mode 100644 index 00000000..4e3fe35a --- /dev/null +++ b/src/deepgram/listen/v2/requests/listen_v2configure.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import typing_extensions +from ....requests.listen_v2keyterm import ListenV2KeytermParams +from .listen_v2configure_thresholds import ListenV2ConfigureThresholdsParams + + +class ListenV2ConfigureParams(typing_extensions.TypedDict): + type: typing.Literal["Configure"] + """ + Message type identifier + """ + + thresholds: typing_extensions.NotRequired[ListenV2ConfigureThresholdsParams] + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + keyterms: typing_extensions.NotRequired[ListenV2KeytermParams] + language_hints: typing_extensions.NotRequired[typing.Sequence[str]] + """ + Language hints to constrain and prioritize language detection. + Only valid when the model is flux-general-multi. If this field is not supplied, + the session will continue to use the currently configured value. + """ diff --git a/src/deepgram/listen/v2/requests/listen_v2configure_failure.py b/src/deepgram/listen/v2/requests/listen_v2configure_failure.py index bfe53f86..4799ff6a 100644 --- a/src/deepgram/listen/v2/requests/listen_v2configure_failure.py +++ b/src/deepgram/listen/v2/requests/listen_v2configure_failure.py @@ -16,7 +16,7 @@ class ListenV2ConfigureFailureParams(typing_extensions.TypedDict): The unique identifier of the request """ - sequence_id: float + sequence_id: int """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/requests/listen_v2configure_success.py b/src/deepgram/listen/v2/requests/listen_v2configure_success.py new file mode 100644 index 00000000..c8e886c7 --- /dev/null +++ b/src/deepgram/listen/v2/requests/listen_v2configure_success.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import typing_extensions +from ....requests.listen_v2keyterm import ListenV2KeytermParams +from .listen_v2configure_success_thresholds import ListenV2ConfigureSuccessThresholdsParams + + +class ListenV2ConfigureSuccessParams(typing_extensions.TypedDict): + type: typing.Literal["ConfigureSuccess"] + """ + Message type identifier + """ + + request_id: str + """ + The unique identifier of the request + """ + + thresholds: ListenV2ConfigureSuccessThresholdsParams + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + keyterms: ListenV2KeytermParams + sequence_id: int + """ + Starts at `0` and increments for each message the server sends + to the client. This includes messages of other types, like + `TurnInfo` messages. + """ diff --git a/src/deepgram/listen/v2/requests/listen_v2configure_success_thresholds.py b/src/deepgram/listen/v2/requests/listen_v2configure_success_thresholds.py new file mode 100644 index 00000000..7a16cdf6 --- /dev/null +++ b/src/deepgram/listen/v2/requests/listen_v2configure_success_thresholds.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +from ....types.listen_v2eager_eot_threshold import ListenV2EagerEotThreshold +from ....types.listen_v2eot_threshold import ListenV2EotThreshold +from ....types.listen_v2eot_timeout_ms import ListenV2EotTimeoutMs + + +class ListenV2ConfigureSuccessThresholdsParams(typing_extensions.TypedDict): + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + eager_eot_threshold: typing_extensions.NotRequired[ListenV2EagerEotThreshold] + eot_threshold: typing_extensions.NotRequired[ListenV2EotThreshold] + eot_timeout_ms: typing_extensions.NotRequired[ListenV2EotTimeoutMs] diff --git a/src/deepgram/listen/v2/requests/listen_v2configure_thresholds.py b/src/deepgram/listen/v2/requests/listen_v2configure_thresholds.py new file mode 100644 index 00000000..4f81602f --- /dev/null +++ b/src/deepgram/listen/v2/requests/listen_v2configure_thresholds.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +from ....types.listen_v2eager_eot_threshold import ListenV2EagerEotThreshold +from ....types.listen_v2eot_threshold import ListenV2EotThreshold +from ....types.listen_v2eot_timeout_ms import ListenV2EotTimeoutMs + + +class ListenV2ConfigureThresholdsParams(typing_extensions.TypedDict): + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + eager_eot_threshold: typing_extensions.NotRequired[ListenV2EagerEotThreshold] + eot_threshold: typing_extensions.NotRequired[ListenV2EotThreshold] + eot_timeout_ms: typing_extensions.NotRequired[ListenV2EotTimeoutMs] diff --git a/src/deepgram/listen/v2/requests/listen_v2connected.py b/src/deepgram/listen/v2/requests/listen_v2connected.py index c931eec2..56ae2a5e 100644 --- a/src/deepgram/listen/v2/requests/listen_v2connected.py +++ b/src/deepgram/listen/v2/requests/listen_v2connected.py @@ -16,7 +16,7 @@ class ListenV2ConnectedParams(typing_extensions.TypedDict): The unique identifier of the request """ - sequence_id: float + sequence_id: int """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/requests/listen_v2fatal_error.py b/src/deepgram/listen/v2/requests/listen_v2fatal_error.py index 05cb3041..1aec4faf 100644 --- a/src/deepgram/listen/v2/requests/listen_v2fatal_error.py +++ b/src/deepgram/listen/v2/requests/listen_v2fatal_error.py @@ -11,7 +11,7 @@ class ListenV2FatalErrorParams(typing_extensions.TypedDict): Message type identifier """ - sequence_id: float + sequence_id: int """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/requests/listen_v2turn_info.py b/src/deepgram/listen/v2/requests/listen_v2turn_info.py index 6690cd2d..71671453 100644 --- a/src/deepgram/listen/v2/requests/listen_v2turn_info.py +++ b/src/deepgram/listen/v2/requests/listen_v2turn_info.py @@ -18,7 +18,7 @@ class ListenV2TurnInfoParams(typing_extensions.TypedDict): The unique identifier of the request """ - sequence_id: float + sequence_id: int """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like `Connected` messages. """ @@ -34,7 +34,7 @@ class ListenV2TurnInfoParams(typing_extensions.TypedDict): - **EndOfTurn** - The user has finished speaking for the turn """ - turn_index: float + turn_index: int """ The index of the current turn """ diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index d214f0f5..696c5938 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -3,12 +3,16 @@ import json import logging 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.unchecked_base_model import construct_type from .types.listen_v2close_stream import ListenV2CloseStream +from .types.listen_v2configure import ListenV2Configure from .types.listen_v2configure_failure import ListenV2ConfigureFailure +from .types.listen_v2configure_success import ListenV2ConfigureSuccess from .types.listen_v2connected import ListenV2Connected from .types.listen_v2fatal_error import ListenV2FatalError from .types.listen_v2turn_info import ListenV2TurnInfo @@ -20,7 +24,7 @@ _logger = logging.getLogger(__name__) V2SocketClientResponse = typing.Union[ - ListenV2Connected, ListenV2TurnInfo, typing.Any, ListenV2ConfigureFailure, ListenV2FatalError + ListenV2Connected, ListenV2TurnInfo, ListenV2ConfigureSuccess, ListenV2ConfigureFailure, ListenV2FatalError ] @@ -67,7 +71,7 @@ async def start_listening(self): ) continue 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) @@ -79,19 +83,19 @@ 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 send_configure(self, message: typing.Any) -> None: + async def send_configure(self, message: ListenV2Configure) -> None: """ Send a message to the websocket connection. - The message will be sent as a typing.Any. + The message will be sent as a ListenV2Configure. """ - await self._send(message) + await self._send_model(message) async def recv(self) -> V2SocketClientResponse: """ @@ -165,7 +169,7 @@ def start_listening(self): ) continue 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) @@ -177,19 +181,19 @@ 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 send_configure(self, message: typing.Any) -> None: + def send_configure(self, message: ListenV2Configure) -> None: """ Send a message to the websocket connection. - The message will be sent as a typing.Any. + The message will be sent as a ListenV2Configure. """ - self._send(message) + self._send_model(message) def recv(self) -> V2SocketClientResponse: """ diff --git a/src/deepgram/listen/v2/types/__init__.py b/src/deepgram/listen/v2/types/__init__.py index 91bab1fe..15cc6fba 100644 --- a/src/deepgram/listen/v2/types/__init__.py +++ b/src/deepgram/listen/v2/types/__init__.py @@ -8,7 +8,11 @@ if typing.TYPE_CHECKING: from .listen_v2close_stream import ListenV2CloseStream from .listen_v2close_stream_type import ListenV2CloseStreamType + from .listen_v2configure import ListenV2Configure from .listen_v2configure_failure import ListenV2ConfigureFailure + from .listen_v2configure_success import ListenV2ConfigureSuccess + from .listen_v2configure_success_thresholds import ListenV2ConfigureSuccessThresholds + from .listen_v2configure_thresholds import ListenV2ConfigureThresholds from .listen_v2connected import ListenV2Connected from .listen_v2fatal_error import ListenV2FatalError from .listen_v2turn_info import ListenV2TurnInfo @@ -17,7 +21,11 @@ _dynamic_imports: typing.Dict[str, str] = { "ListenV2CloseStream": ".listen_v2close_stream", "ListenV2CloseStreamType": ".listen_v2close_stream_type", + "ListenV2Configure": ".listen_v2configure", "ListenV2ConfigureFailure": ".listen_v2configure_failure", + "ListenV2ConfigureSuccess": ".listen_v2configure_success", + "ListenV2ConfigureSuccessThresholds": ".listen_v2configure_success_thresholds", + "ListenV2ConfigureThresholds": ".listen_v2configure_thresholds", "ListenV2Connected": ".listen_v2connected", "ListenV2FatalError": ".listen_v2fatal_error", "ListenV2TurnInfo": ".listen_v2turn_info", @@ -50,7 +58,11 @@ def __dir__(): __all__ = [ "ListenV2CloseStream", "ListenV2CloseStreamType", + "ListenV2Configure", "ListenV2ConfigureFailure", + "ListenV2ConfigureSuccess", + "ListenV2ConfigureSuccessThresholds", + "ListenV2ConfigureThresholds", "ListenV2Connected", "ListenV2FatalError", "ListenV2TurnInfo", diff --git a/src/deepgram/listen/v2/types/listen_v2configure.py b/src/deepgram/listen/v2/types/listen_v2configure.py new file mode 100644 index 00000000..6ecb59ca --- /dev/null +++ b/src/deepgram/listen/v2/types/listen_v2configure.py @@ -0,0 +1,39 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel +from ....types.listen_v2keyterm import ListenV2Keyterm +from .listen_v2configure_thresholds import ListenV2ConfigureThresholds + + +class ListenV2Configure(UncheckedBaseModel): + type: typing.Literal["Configure"] = pydantic.Field(default="Configure") + """ + Message type identifier + """ + + thresholds: typing.Optional[ListenV2ConfigureThresholds] = pydantic.Field(default=None) + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + keyterms: typing.Optional[ListenV2Keyterm] = None + language_hints: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + Language hints to constrain and prioritize language detection. + Only valid when the model is flux-general-multi. If this field is not supplied, + the session will continue to use the currently configured value. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/listen/v2/types/listen_v2configure_failure.py b/src/deepgram/listen/v2/types/listen_v2configure_failure.py index b00fc6b1..2d0cb34f 100644 --- a/src/deepgram/listen/v2/types/listen_v2configure_failure.py +++ b/src/deepgram/listen/v2/types/listen_v2configure_failure.py @@ -18,7 +18,7 @@ class ListenV2ConfigureFailure(UncheckedBaseModel): The unique identifier of the request """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/types/listen_v2configure_success.py b/src/deepgram/listen/v2/types/listen_v2configure_success.py new file mode 100644 index 00000000..3fd7a556 --- /dev/null +++ b/src/deepgram/listen/v2/types/listen_v2configure_success.py @@ -0,0 +1,44 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel +from ....types.listen_v2keyterm import ListenV2Keyterm +from .listen_v2configure_success_thresholds import ListenV2ConfigureSuccessThresholds + + +class ListenV2ConfigureSuccess(UncheckedBaseModel): + type: typing.Literal["ConfigureSuccess"] = pydantic.Field(default="ConfigureSuccess") + """ + Message type identifier + """ + + request_id: str = pydantic.Field() + """ + The unique identifier of the request + """ + + thresholds: ListenV2ConfigureSuccessThresholds = pydantic.Field() + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + keyterms: ListenV2Keyterm + sequence_id: int = pydantic.Field() + """ + Starts at `0` and increments for each message the server sends + to the client. This includes messages of other types, like + `TurnInfo` messages. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/listen/v2/types/listen_v2configure_success_thresholds.py b/src/deepgram/listen/v2/types/listen_v2configure_success_thresholds.py new file mode 100644 index 00000000..6c719233 --- /dev/null +++ b/src/deepgram/listen/v2/types/listen_v2configure_success_thresholds.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel +from ....types.listen_v2eager_eot_threshold import ListenV2EagerEotThreshold +from ....types.listen_v2eot_threshold import ListenV2EotThreshold +from ....types.listen_v2eot_timeout_ms import ListenV2EotTimeoutMs + + +class ListenV2ConfigureSuccessThresholds(UncheckedBaseModel): + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + eager_eot_threshold: typing.Optional[ListenV2EagerEotThreshold] = None + eot_threshold: typing.Optional[ListenV2EotThreshold] = None + eot_timeout_ms: typing.Optional[ListenV2EotTimeoutMs] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/listen/v2/types/listen_v2configure_thresholds.py b/src/deepgram/listen/v2/types/listen_v2configure_thresholds.py new file mode 100644 index 00000000..b992c5d8 --- /dev/null +++ b/src/deepgram/listen/v2/types/listen_v2configure_thresholds.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.unchecked_base_model import UncheckedBaseModel +from ....types.listen_v2eager_eot_threshold import ListenV2EagerEotThreshold +from ....types.listen_v2eot_threshold import ListenV2EotThreshold +from ....types.listen_v2eot_timeout_ms import ListenV2EotTimeoutMs + + +class ListenV2ConfigureThresholds(UncheckedBaseModel): + """ + Updates each parameter, if it is supplied. If a particular threshold parameter + is not supplied, the configuration continues using the currently configured value. + """ + + eager_eot_threshold: typing.Optional[ListenV2EagerEotThreshold] = None + eot_threshold: typing.Optional[ListenV2EotThreshold] = None + eot_timeout_ms: typing.Optional[ListenV2EotTimeoutMs] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/deepgram/listen/v2/types/listen_v2connected.py b/src/deepgram/listen/v2/types/listen_v2connected.py index b174be68..cefc0236 100644 --- a/src/deepgram/listen/v2/types/listen_v2connected.py +++ b/src/deepgram/listen/v2/types/listen_v2connected.py @@ -18,7 +18,7 @@ class ListenV2Connected(UncheckedBaseModel): The unique identifier of the request """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/types/listen_v2fatal_error.py b/src/deepgram/listen/v2/types/listen_v2fatal_error.py index 0e65c00e..c5106f07 100644 --- a/src/deepgram/listen/v2/types/listen_v2fatal_error.py +++ b/src/deepgram/listen/v2/types/listen_v2fatal_error.py @@ -13,7 +13,7 @@ class ListenV2FatalError(UncheckedBaseModel): Message type identifier """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like diff --git a/src/deepgram/listen/v2/types/listen_v2turn_info.py b/src/deepgram/listen/v2/types/listen_v2turn_info.py index 96f05688..dd60abf5 100644 --- a/src/deepgram/listen/v2/types/listen_v2turn_info.py +++ b/src/deepgram/listen/v2/types/listen_v2turn_info.py @@ -20,7 +20,7 @@ class ListenV2TurnInfo(UncheckedBaseModel): The unique identifier of the request """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ Starts at `0` and increments for each message the server sends to the client. This includes messages of other types, like `Connected` messages. """ @@ -36,7 +36,7 @@ class ListenV2TurnInfo(UncheckedBaseModel): - **EndOfTurn** - The user has finished speaking for the turn """ - turn_index: float = pydantic.Field() + turn_index: int = pydantic.Field() """ The index of the current turn """ diff --git a/src/deepgram/manage/v1/models/raw_client.py b/src/deepgram/manage/v1/models/raw_client.py index 645700c9..450d5463 100644 --- a/src/deepgram/manage/v1/models/raw_client.py +++ b/src/deepgram/manage/v1/models/raw_client.py @@ -6,12 +6,14 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.jsonable_encoder import jsonable_encoder +from ....core.jsonable_encoder import encode_path_param +from ....core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawModelsClient: @@ -70,6 +72,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -92,7 +98,7 @@ def get( A model object that can be either STT or TTS """ _response = self._client_wrapper.httpx_client.request( - f"v1/models/{jsonable_encoder(model_id)}", + f"v1/models/{encode_path_param(model_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -121,6 +127,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -180,6 +190,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -202,7 +216,7 @@ async def get( A model object that can be either STT or TTS """ _response = await self._client_wrapper.httpx_client.request( - f"v1/models/{jsonable_encoder(model_id)}", + f"v1/models/{encode_path_param(model_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -231,4 +245,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 c3794fb5..c2c2bd84 100644 --- a/src/deepgram/manage/v1/projects/billing/balances/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/balances/raw_client.py @@ -6,12 +6,14 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawBalancesClient: @@ -38,7 +40,7 @@ def list( A list of outstanding balances """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/balances", + f"v1/projects/{encode_path_param(project_id)}/balances", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -67,6 +69,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -92,7 +98,7 @@ def get( A specific balance """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/balances/{jsonable_encoder(balance_id)}", + f"v1/projects/{encode_path_param(project_id)}/balances/{encode_path_param(balance_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -121,6 +127,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -148,7 +158,7 @@ async def list( A list of outstanding balances """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/balances", + f"v1/projects/{encode_path_param(project_id)}/balances", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -177,6 +187,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -202,7 +216,7 @@ async def get( A specific balance """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/balances/{jsonable_encoder(balance_id)}", + f"v1/projects/{encode_path_param(project_id)}/balances/{encode_path_param(balance_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -231,4 +245,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/manage/v1/projects/billing/breakdown/client.py b/src/deepgram/manage/v1/projects/billing/breakdown/client.py index 34bfbcf0..81efaf56 100644 --- a/src/deepgram/manage/v1/projects/billing/breakdown/client.py +++ b/src/deepgram/manage/v1/projects/billing/breakdown/client.py @@ -92,6 +92,7 @@ def list( deployment="hosted", tag="tag1", line_item="streaming::nova-3", + grouping=["deployment", "line_item"], ) """ _response = self._raw_client.list( @@ -195,6 +196,7 @@ async def main() -> None: deployment="hosted", tag="tag1", line_item="streaming::nova-3", + grouping=["deployment", "line_item"], ) 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 42bcf865..41918a00 100644 --- a/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/breakdown/raw_client.py @@ -6,13 +6,15 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 from .types.breakdown_list_request_grouping_item import BreakdownListRequestGroupingItem +from pydantic import ValidationError class RawBreakdownClient: @@ -72,7 +74,7 @@ def list( Billing breakdown response """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/billing/breakdown", + f"v1/projects/{encode_path_param(project_id)}/billing/breakdown", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -110,6 +112,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -170,7 +176,7 @@ async def list( Billing breakdown response """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/billing/breakdown", + f"v1/projects/{encode_path_param(project_id)}/billing/breakdown", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -208,4 +214,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 ec97bccc..26d0601f 100644 --- a/src/deepgram/manage/v1/projects/billing/fields/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/fields/raw_client.py @@ -6,11 +6,13 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawFieldsClient: @@ -48,7 +50,7 @@ def list( A list of billing fields for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/billing/fields", + f"v1/projects/{encode_path_param(project_id)}/billing/fields", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -81,6 +83,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -119,7 +125,7 @@ async def list( A list of billing fields for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/billing/fields", + f"v1/projects/{encode_path_param(project_id)}/billing/fields", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -152,4 +158,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 02621660..2520355f 100644 --- a/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py +++ b/src/deepgram/manage/v1/projects/billing/purchases/raw_client.py @@ -6,11 +6,13 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawPurchasesClient: @@ -44,7 +46,7 @@ def list( A list of purchases for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/purchases", + f"v1/projects/{encode_path_param(project_id)}/purchases", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -76,6 +78,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -110,7 +116,7 @@ async def list( A list of purchases for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/purchases", + f"v1/projects/{encode_path_param(project_id)}/purchases", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -142,4 +148,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 60c81ff6..05acd81c 100644 --- a/src/deepgram/manage/v1/projects/keys/raw_client.py +++ b/src/deepgram/manage/v1/projects/keys/raw_client.py @@ -6,7 +6,8 @@ from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse -from .....core.jsonable_encoder import jsonable_encoder +from .....core.jsonable_encoder import encode_path_param +from .....core.parse_error import ParsingError from .....core.request_options import RequestOptions from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError @@ -16,6 +17,7 @@ from .....types.get_project_key_v1response import GetProjectKeyV1Response from .....types.list_project_keys_v1response import ListProjectKeysV1Response from .types.keys_list_request_status import KeysListRequestStatus +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -52,7 +54,7 @@ def list( A list of API keys """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys", + f"v1/projects/{encode_path_param(project_id)}/keys", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -84,6 +86,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -112,7 +118,7 @@ def create( API key created successfully """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys", + f"v1/projects/{encode_path_param(project_id)}/keys", base_url=self._client_wrapper.get_environment().base, method="POST", json=request, @@ -146,6 +152,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -171,7 +181,7 @@ def get( A specific API key """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys/{jsonable_encoder(key_id)}", + f"v1/projects/{encode_path_param(project_id)}/keys/{encode_path_param(key_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -200,6 +210,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -225,7 +239,7 @@ def delete( API key deleted """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys/{jsonable_encoder(key_id)}", + f"v1/projects/{encode_path_param(project_id)}/keys/{encode_path_param(key_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -254,6 +268,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -288,7 +306,7 @@ async def list( A list of API keys """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys", + f"v1/projects/{encode_path_param(project_id)}/keys", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -320,6 +338,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -348,7 +370,7 @@ async def create( API key created successfully """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys", + f"v1/projects/{encode_path_param(project_id)}/keys", base_url=self._client_wrapper.get_environment().base, method="POST", json=request, @@ -382,6 +404,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -407,7 +433,7 @@ async def get( A specific API key """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys/{jsonable_encoder(key_id)}", + f"v1/projects/{encode_path_param(project_id)}/keys/{encode_path_param(key_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -436,6 +462,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -461,7 +491,7 @@ async def delete( API key deleted """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/keys/{jsonable_encoder(key_id)}", + f"v1/projects/{encode_path_param(project_id)}/keys/{encode_path_param(key_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -490,4 +520,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 05824c5d..e090c46c 100644 --- a/src/deepgram/manage/v1/projects/members/invites/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/invites/raw_client.py @@ -6,13 +6,15 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 from ......types.list_project_invites_v1response import ListProjectInvitesV1Response +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -42,7 +44,7 @@ def list( A list of invites for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites", + f"v1/projects/{encode_path_param(project_id)}/invites", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -71,6 +73,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -99,7 +105,7 @@ def create( The invite was successfully generated """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites", + f"v1/projects/{encode_path_param(project_id)}/invites", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -136,6 +142,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -161,7 +171,7 @@ def delete( The invite was successfully deleted """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites/{jsonable_encoder(email)}", + f"v1/projects/{encode_path_param(project_id)}/invites/{encode_path_param(email)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -190,6 +200,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -217,7 +231,7 @@ async def list( A list of invites for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites", + f"v1/projects/{encode_path_param(project_id)}/invites", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -246,6 +260,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -274,7 +292,7 @@ async def create( The invite was successfully generated """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites", + f"v1/projects/{encode_path_param(project_id)}/invites", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -311,6 +329,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -336,7 +358,7 @@ async def delete( The invite was successfully deleted """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/invites/{jsonable_encoder(email)}", + f"v1/projects/{encode_path_param(project_id)}/invites/{encode_path_param(email)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -365,4 +387,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 b72c342d..d3dbdd49 100644 --- a/src/deepgram/manage/v1/projects/members/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/raw_client.py @@ -6,12 +6,14 @@ from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse -from .....core.jsonable_encoder import jsonable_encoder +from .....core.jsonable_encoder import encode_path_param +from .....core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawMembersClient: @@ -38,7 +40,7 @@ def list( A list of members for a given project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members", + f"v1/projects/{encode_path_param(project_id)}/members", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -67,6 +69,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -92,7 +98,7 @@ def delete( Delete the specific member from the project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -121,6 +127,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -148,7 +158,7 @@ async def list( A list of members for a given project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members", + f"v1/projects/{encode_path_param(project_id)}/members", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -177,6 +187,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -202,7 +216,7 @@ async def delete( Delete the specific member from the project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -231,4 +245,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 6645527c..7102d9d1 100644 --- a/src/deepgram/manage/v1/projects/members/scopes/raw_client.py +++ b/src/deepgram/manage/v1/projects/members/scopes/raw_client.py @@ -6,12 +6,14 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -44,7 +46,7 @@ def list( A list of scopes for a specific member """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}/scopes", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}/scopes", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -73,6 +75,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update( @@ -101,7 +107,7 @@ def update( Updated the scopes for a specific member """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}/scopes", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}/scopes", base_url=self._client_wrapper.get_environment().base, method="PUT", json={ @@ -137,6 +143,10 @@ def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -167,7 +177,7 @@ async def list( A list of scopes for a specific member """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}/scopes", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}/scopes", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -196,6 +206,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update( @@ -224,7 +238,7 @@ async def update( Updated the scopes for a specific member """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/members/{jsonable_encoder(member_id)}/scopes", + f"v1/projects/{encode_path_param(project_id)}/members/{encode_path_param(member_id)}/scopes", base_url=self._client_wrapper.get_environment().base, method="PUT", json={ @@ -260,4 +274,8 @@ async def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 fa9b7cde..689714fb 100644 --- a/src/deepgram/manage/v1/projects/models/raw_client.py +++ b/src/deepgram/manage/v1/projects/models/raw_client.py @@ -6,12 +6,14 @@ from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse -from .....core.jsonable_encoder import jsonable_encoder +from .....core.jsonable_encoder import encode_path_param +from .....core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawModelsClient: @@ -45,7 +47,7 @@ def list( A list of models """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/models", + f"v1/projects/{encode_path_param(project_id)}/models", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -77,6 +79,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -102,7 +108,7 @@ def get( A model object that can be either STT or TTS """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/models/{jsonable_encoder(model_id)}", + f"v1/projects/{encode_path_param(project_id)}/models/{encode_path_param(model_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -131,6 +137,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -165,7 +175,7 @@ async def list( A list of models """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/models", + f"v1/projects/{encode_path_param(project_id)}/models", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -197,6 +207,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -222,7 +236,7 @@ async def get( A model object that can be either STT or TTS """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/models/{jsonable_encoder(model_id)}", + f"v1/projects/{encode_path_param(project_id)}/models/{encode_path_param(model_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -251,4 +265,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/manage/v1/projects/raw_client.py b/src/deepgram/manage/v1/projects/raw_client.py index 05afa3c9..2504ac3c 100644 --- a/src/deepgram/manage/v1/projects/raw_client.py +++ b/src/deepgram/manage/v1/projects/raw_client.py @@ -6,7 +6,8 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.jsonable_encoder import jsonable_encoder +from ....core.jsonable_encoder import encode_path_param +from ....core.parse_error import ParsingError from ....core.request_options import RequestOptions from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError @@ -15,6 +16,7 @@ from ....types.leave_project_v1response import LeaveProjectV1Response from ....types.list_projects_v1response import ListProjectsV1Response from ....types.update_project_v1response import UpdateProjectV1Response +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -68,6 +70,10 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -101,7 +107,7 @@ def get( A project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -134,6 +140,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -156,7 +166,7 @@ def delete( A project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -185,6 +195,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update( @@ -214,7 +228,7 @@ def update( A project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ @@ -250,6 +264,10 @@ def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def leave( @@ -272,7 +290,7 @@ def leave( Successfully removed account from project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/leave", + f"v1/projects/{encode_path_param(project_id)}/leave", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -301,6 +319,10 @@ def leave( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -354,6 +376,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -387,7 +413,7 @@ async def get( A project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -420,6 +446,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -442,7 +472,7 @@ async def delete( A project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -471,6 +501,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update( @@ -500,7 +534,7 @@ async def update( A project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}", + f"v1/projects/{encode_path_param(project_id)}", base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ @@ -536,6 +570,10 @@ async def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def leave( @@ -558,7 +596,7 @@ async def leave( Successfully removed account from project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/leave", + f"v1/projects/{encode_path_param(project_id)}/leave", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -587,4 +625,8 @@ async def leave( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 65befe11..f5a739d3 100644 --- a/src/deepgram/manage/v1/projects/requests/raw_client.py +++ b/src/deepgram/manage/v1/projects/requests/raw_client.py @@ -8,7 +8,8 @@ from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.datetime_utils import serialize_datetime from .....core.http_response import AsyncHttpResponse, HttpResponse -from .....core.jsonable_encoder import jsonable_encoder +from .....core.jsonable_encoder import encode_path_param +from .....core.parse_error import ParsingError from .....core.request_options import RequestOptions from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError @@ -18,6 +19,7 @@ from .types.requests_list_request_endpoint import RequestsListRequestEndpoint from .types.requests_list_request_method import RequestsListRequestMethod from .types.requests_list_request_status import RequestsListRequestStatus +from pydantic import ValidationError class RawRequestsClient: @@ -87,7 +89,7 @@ def list( A list of requests for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/requests", + f"v1/projects/{encode_path_param(project_id)}/requests", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -128,6 +130,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -153,7 +159,7 @@ def get( A specific request for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/requests/{jsonable_encoder(request_id)}", + f"v1/projects/{encode_path_param(project_id)}/requests/{encode_path_param(request_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -182,6 +188,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -252,7 +262,7 @@ async def list( A list of requests for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/requests", + f"v1/projects/{encode_path_param(project_id)}/requests", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -293,6 +303,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -318,7 +332,7 @@ async def get( A specific request for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/requests/{jsonable_encoder(request_id)}", + f"v1/projects/{encode_path_param(project_id)}/requests/{encode_path_param(request_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -347,4 +361,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 9e6788a8..53b499ae 100644 --- a/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/breakdown/raw_client.py @@ -6,7 +6,8 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError from ......core.request_options import RequestOptions from ......core.unchecked_base_model import construct_type from ......errors.bad_request_error import BadRequestError @@ -15,6 +16,7 @@ from .types.breakdown_get_request_endpoint import BreakdownGetRequestEndpoint from .types.breakdown_get_request_grouping import BreakdownGetRequestGrouping from .types.breakdown_get_request_method import BreakdownGetRequestMethod +from pydantic import ValidationError class RawBreakdownClient: @@ -224,7 +226,7 @@ def get( Usage breakdown response """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage/breakdown", + f"v1/projects/{encode_path_param(project_id)}/usage/breakdown", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -300,6 +302,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -510,7 +516,7 @@ async def get( Usage breakdown response """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage/breakdown", + f"v1/projects/{encode_path_param(project_id)}/usage/breakdown", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -586,4 +592,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 275f485a..bcdbc202 100644 --- a/src/deepgram/manage/v1/projects/usage/fields/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/fields/raw_client.py @@ -6,11 +6,13 @@ from ......core.api_error import ApiError from ......core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ......core.http_response import AsyncHttpResponse, HttpResponse -from ......core.jsonable_encoder import jsonable_encoder +from ......core.jsonable_encoder import encode_path_param +from ......core.parse_error import ParsingError 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 +from pydantic import ValidationError class RawFieldsClient: @@ -48,7 +50,7 @@ def list( A list of fields for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage/fields", + f"v1/projects/{encode_path_param(project_id)}/usage/fields", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -81,6 +83,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -119,7 +125,7 @@ async def list( A list of fields for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage/fields", + f"v1/projects/{encode_path_param(project_id)}/usage/fields", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -152,4 +158,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_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 c8a6e3a3..8c544cb7 100644 --- a/src/deepgram/manage/v1/projects/usage/raw_client.py +++ b/src/deepgram/manage/v1/projects/usage/raw_client.py @@ -6,7 +6,8 @@ from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.http_response import AsyncHttpResponse, HttpResponse -from .....core.jsonable_encoder import jsonable_encoder +from .....core.jsonable_encoder import encode_path_param +from .....core.parse_error import ParsingError from .....core.request_options import RequestOptions from .....core.unchecked_base_model import construct_type from .....errors.bad_request_error import BadRequestError @@ -14,6 +15,7 @@ from .types.usage_get_request_deployment import UsageGetRequestDeployment from .types.usage_get_request_endpoint import UsageGetRequestEndpoint from .types.usage_get_request_method import UsageGetRequestMethod +from pydantic import ValidationError class RawUsageClient: @@ -219,7 +221,7 @@ def get( A specific request for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage", + f"v1/projects/{encode_path_param(project_id)}/usage", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -294,6 +296,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -500,7 +506,7 @@ async def get( A specific request for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/usage", + f"v1/projects/{encode_path_param(project_id)}/usage", base_url=self._client_wrapper.get_environment().base, method="GET", params={ @@ -575,4 +581,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/read/v1/text/raw_client.py b/src/deepgram/read/v1/text/raw_client.py index 65b7ebca..35c2bf0e 100644 --- a/src/deepgram/read/v1/text/raw_client.py +++ b/src/deepgram/read/v1/text/raw_client.py @@ -6,6 +6,7 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse +from ....core.parse_error import ParsingError from ....core.request_options import RequestOptions from ....core.serialization import convert_and_respect_annotation_metadata from ....core.unchecked_base_model import construct_type @@ -16,6 +17,7 @@ from .types.text_analyze_request_custom_intent_mode import TextAnalyzeRequestCustomIntentMode from .types.text_analyze_request_custom_topic_mode import TextAnalyzeRequestCustomTopicMode from .types.text_analyze_request_summarize import TextAnalyzeRequestSummarize +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -145,6 +147,10 @@ def analyze( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -272,4 +278,8 @@ async def analyze( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/requests/listen_v1response_metadata.py b/src/deepgram/requests/listen_v1response_metadata.py index 7a1671ac..100cb4a1 100644 --- a/src/deepgram/requests/listen_v1response_metadata.py +++ b/src/deepgram/requests/listen_v1response_metadata.py @@ -16,7 +16,7 @@ class ListenV1ResponseMetadataParams(typing_extensions.TypedDict): sha256: str created: dt.datetime duration: float - channels: float + channels: int models: typing.Sequence[str] model_info: typing.Dict[str, typing.Any] summary_info: typing_extensions.NotRequired[ListenV1ResponseMetadataSummaryInfoParams] diff --git a/src/deepgram/requests/listen_v1response_metadata_intents_info.py b/src/deepgram/requests/listen_v1response_metadata_intents_info.py index 88bd5043..78c106bd 100644 --- a/src/deepgram/requests/listen_v1response_metadata_intents_info.py +++ b/src/deepgram/requests/listen_v1response_metadata_intents_info.py @@ -5,5 +5,5 @@ class ListenV1ResponseMetadataIntentsInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/listen_v1response_metadata_sentiment_info.py b/src/deepgram/requests/listen_v1response_metadata_sentiment_info.py index a92d108d..e26b7621 100644 --- a/src/deepgram/requests/listen_v1response_metadata_sentiment_info.py +++ b/src/deepgram/requests/listen_v1response_metadata_sentiment_info.py @@ -5,5 +5,5 @@ class ListenV1ResponseMetadataSentimentInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/listen_v1response_metadata_summary_info.py b/src/deepgram/requests/listen_v1response_metadata_summary_info.py index ea1b51f0..95f2f812 100644 --- a/src/deepgram/requests/listen_v1response_metadata_summary_info.py +++ b/src/deepgram/requests/listen_v1response_metadata_summary_info.py @@ -5,5 +5,5 @@ class ListenV1ResponseMetadataSummaryInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/listen_v1response_metadata_topics_info.py b/src/deepgram/requests/listen_v1response_metadata_topics_info.py index a6ddbc49..9f2ead53 100644 --- a/src/deepgram/requests/listen_v1response_metadata_topics_info.py +++ b/src/deepgram/requests/listen_v1response_metadata_topics_info.py @@ -5,5 +5,5 @@ class ListenV1ResponseMetadataTopicsInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py b/src/deepgram/requests/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py index 6c35ddb1..c0a334e1 100644 --- a/src/deepgram/requests/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py +++ b/src/deepgram/requests/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py @@ -12,7 +12,7 @@ class ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsIte sentences: typing_extensions.NotRequired[ typing.Sequence[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItemParams] ] - speaker: typing_extensions.NotRequired[float] - num_words: typing_extensions.NotRequired[float] + speaker: typing_extensions.NotRequired[int] + num_words: typing_extensions.NotRequired[int] start: typing_extensions.NotRequired[float] end: typing_extensions.NotRequired[float] diff --git a/src/deepgram/requests/listen_v1response_results_utterances_item.py b/src/deepgram/requests/listen_v1response_results_utterances_item.py index 8298c202..82fba7f9 100644 --- a/src/deepgram/requests/listen_v1response_results_utterances_item.py +++ b/src/deepgram/requests/listen_v1response_results_utterances_item.py @@ -10,8 +10,8 @@ class ListenV1ResponseResultsUtterancesItemParams(typing_extensions.TypedDict): start: typing_extensions.NotRequired[float] end: typing_extensions.NotRequired[float] confidence: typing_extensions.NotRequired[float] - channel: typing_extensions.NotRequired[float] + channel: typing_extensions.NotRequired[int] transcript: typing_extensions.NotRequired[str] words: typing_extensions.NotRequired[typing.Sequence[ListenV1ResponseResultsUtterancesItemWordsItemParams]] - speaker: typing_extensions.NotRequired[float] + speaker: typing_extensions.NotRequired[int] id: typing_extensions.NotRequired[str] diff --git a/src/deepgram/requests/listen_v1response_results_utterances_item_words_item.py b/src/deepgram/requests/listen_v1response_results_utterances_item_words_item.py index ea2bbf42..8ec08cc9 100644 --- a/src/deepgram/requests/listen_v1response_results_utterances_item_words_item.py +++ b/src/deepgram/requests/listen_v1response_results_utterances_item_words_item.py @@ -8,6 +8,6 @@ class ListenV1ResponseResultsUtterancesItemWordsItemParams(typing_extensions.Typ start: typing_extensions.NotRequired[float] end: typing_extensions.NotRequired[float] confidence: typing_extensions.NotRequired[float] - speaker: typing_extensions.NotRequired[float] + speaker: typing_extensions.NotRequired[int] speaker_confidence: typing_extensions.NotRequired[float] punctuated_word: typing_extensions.NotRequired[str] diff --git a/src/deepgram/requests/read_v1response_metadata_metadata_intents_info.py b/src/deepgram/requests/read_v1response_metadata_metadata_intents_info.py index 6aab9ec3..ac0961bc 100644 --- a/src/deepgram/requests/read_v1response_metadata_metadata_intents_info.py +++ b/src/deepgram/requests/read_v1response_metadata_metadata_intents_info.py @@ -5,5 +5,5 @@ class ReadV1ResponseMetadataMetadataIntentsInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/read_v1response_metadata_metadata_sentiment_info.py b/src/deepgram/requests/read_v1response_metadata_metadata_sentiment_info.py index e9ac60d3..8f17e6da 100644 --- a/src/deepgram/requests/read_v1response_metadata_metadata_sentiment_info.py +++ b/src/deepgram/requests/read_v1response_metadata_metadata_sentiment_info.py @@ -5,5 +5,5 @@ class ReadV1ResponseMetadataMetadataSentimentInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/read_v1response_metadata_metadata_summary_info.py b/src/deepgram/requests/read_v1response_metadata_metadata_summary_info.py index 6ab5a0ff..cb2a159b 100644 --- a/src/deepgram/requests/read_v1response_metadata_metadata_summary_info.py +++ b/src/deepgram/requests/read_v1response_metadata_metadata_summary_info.py @@ -5,5 +5,5 @@ class ReadV1ResponseMetadataMetadataSummaryInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/requests/read_v1response_metadata_metadata_topics_info.py b/src/deepgram/requests/read_v1response_metadata_metadata_topics_info.py index ad718351..3ae2f074 100644 --- a/src/deepgram/requests/read_v1response_metadata_metadata_topics_info.py +++ b/src/deepgram/requests/read_v1response_metadata_metadata_topics_info.py @@ -5,5 +5,5 @@ class ReadV1ResponseMetadataMetadataTopicsInfoParams(typing_extensions.TypedDict): model_uuid: typing_extensions.NotRequired[str] - input_tokens: typing_extensions.NotRequired[float] - output_tokens: typing_extensions.NotRequired[float] + input_tokens: typing_extensions.NotRequired[int] + output_tokens: typing_extensions.NotRequired[int] diff --git a/src/deepgram/self_hosted/v1/distribution_credentials/client.py b/src/deepgram/self_hosted/v1/distribution_credentials/client.py index 63371d29..c0c63b10 100644 --- a/src/deepgram/self_hosted/v1/distribution_credentials/client.py +++ b/src/deepgram/self_hosted/v1/distribution_credentials/client.py @@ -110,6 +110,7 @@ def create( ) client.self_hosted.v1.distribution_credentials.create( project_id="123456-7890-1234-5678-901234", + scopes=["self-hosted:products"], ) """ _response = self._raw_client.create( @@ -309,6 +310,7 @@ async def create( async def main() -> None: await client.self_hosted.v1.distribution_credentials.create( project_id="123456-7890-1234-5678-901234", + scopes=["self-hosted:products"], ) 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 f7e60ef9..63191eea 100644 --- a/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py +++ b/src/deepgram/self_hosted/v1/distribution_credentials/raw_client.py @@ -6,7 +6,8 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse -from ....core.jsonable_encoder import jsonable_encoder +from ....core.jsonable_encoder import encode_path_param +from ....core.parse_error import ParsingError from ....core.request_options import RequestOptions from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError @@ -14,6 +15,7 @@ from ....types.get_project_distribution_credentials_v1response import GetProjectDistributionCredentialsV1Response from ....types.list_project_distribution_credentials_v1response import ListProjectDistributionCredentialsV1Response from .types.distribution_credentials_create_request_scopes_item import DistributionCredentialsCreateRequestScopesItem +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -43,7 +45,7 @@ def list( A list of distribution credentials for a specific project """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -72,6 +74,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -114,7 +120,7 @@ def create( Single distribution credential """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials", base_url=self._client_wrapper.get_environment().base, method="POST", params={ @@ -154,6 +160,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -183,7 +193,7 @@ def get( Single distribution credential """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials/{jsonable_encoder(distribution_credentials_id)}", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials/{encode_path_param(distribution_credentials_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -212,6 +222,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -241,7 +255,7 @@ def delete( Single distribution credential """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials/{jsonable_encoder(distribution_credentials_id)}", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials/{encode_path_param(distribution_credentials_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -270,6 +284,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -297,7 +315,7 @@ async def list( A list of distribution credentials for a specific project """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -326,6 +344,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -368,7 +390,7 @@ async def create( Single distribution credential """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials", base_url=self._client_wrapper.get_environment().base, method="POST", params={ @@ -408,6 +430,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -437,7 +463,7 @@ async def get( Single distribution credential """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials/{jsonable_encoder(distribution_credentials_id)}", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials/{encode_path_param(distribution_credentials_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -466,6 +492,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -495,7 +525,7 @@ async def delete( Single distribution credential """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/self-hosted/distribution/credentials/{jsonable_encoder(distribution_credentials_id)}", + f"v1/projects/{encode_path_param(project_id)}/self-hosted/distribution/credentials/{encode_path_param(distribution_credentials_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -524,4 +554,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/speak/v1/audio/raw_client.py b/src/deepgram/speak/v1/audio/raw_client.py index 641512af..3d186fb0 100644 --- a/src/deepgram/speak/v1/audio/raw_client.py +++ b/src/deepgram/speak/v1/audio/raw_client.py @@ -7,6 +7,7 @@ from ....core.api_error import ApiError from ....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ....core.http_response import AsyncHttpResponse, HttpResponse +from ....core.parse_error import ParsingError from ....core.request_options import RequestOptions from ....core.unchecked_base_model import construct_type from ....errors.bad_request_error import BadRequestError @@ -14,6 +15,7 @@ from .types.audio_generate_request_container import AudioGenerateRequestContainer from .types.audio_generate_request_encoding import AudioGenerateRequestEncoding from .types.audio_generate_request_model import AudioGenerateRequestModel +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -131,6 +133,13 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: raise ApiError( status_code=_response.status_code, headers=dict(_response.headers), body=_response.text ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) yield _stream() @@ -249,6 +258,13 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: raise ApiError( status_code=_response.status_code, headers=dict(_response.headers), body=_response.text ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) yield await _stream() diff --git a/src/deepgram/speak/v1/requests/speak_v1cleared.py b/src/deepgram/speak/v1/requests/speak_v1cleared.py index e1f1784b..7cfa78c1 100644 --- a/src/deepgram/speak/v1/requests/speak_v1cleared.py +++ b/src/deepgram/speak/v1/requests/speak_v1cleared.py @@ -10,7 +10,7 @@ class SpeakV1ClearedParams(typing_extensions.TypedDict): Message type identifier """ - sequence_id: float + sequence_id: int """ The sequence ID of the response """ diff --git a/src/deepgram/speak/v1/requests/speak_v1flushed.py b/src/deepgram/speak/v1/requests/speak_v1flushed.py index 674cb52d..ccf8a1fc 100644 --- a/src/deepgram/speak/v1/requests/speak_v1flushed.py +++ b/src/deepgram/speak/v1/requests/speak_v1flushed.py @@ -10,7 +10,7 @@ class SpeakV1FlushedParams(typing_extensions.TypedDict): Message type identifier """ - sequence_id: float + sequence_id: int """ The sequence ID of the response """ diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index e3c28bb5..9f1cad28 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -3,7 +3,9 @@ import json import logging 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.unchecked_base_model import construct_type @@ -68,7 +70,7 @@ async def start_listening(self): ) continue 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) @@ -80,26 +82,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: """ @@ -173,7 +175,7 @@ def start_listening(self): ) continue 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) @@ -185,26 +187,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/src/deepgram/speak/v1/types/speak_v1cleared.py b/src/deepgram/speak/v1/types/speak_v1cleared.py index 06328648..4966f54a 100644 --- a/src/deepgram/speak/v1/types/speak_v1cleared.py +++ b/src/deepgram/speak/v1/types/speak_v1cleared.py @@ -14,7 +14,7 @@ class SpeakV1Cleared(UncheckedBaseModel): Message type identifier """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ The sequence ID of the response """ diff --git a/src/deepgram/speak/v1/types/speak_v1flushed.py b/src/deepgram/speak/v1/types/speak_v1flushed.py index b1e4b127..c555a2f7 100644 --- a/src/deepgram/speak/v1/types/speak_v1flushed.py +++ b/src/deepgram/speak/v1/types/speak_v1flushed.py @@ -14,7 +14,7 @@ class SpeakV1Flushed(UncheckedBaseModel): Message type identifier """ - sequence_id: float = pydantic.Field() + sequence_id: int = pydantic.Field() """ The sequence ID of the response """ diff --git a/src/deepgram/types/delete_agent_configuration_v1response.py b/src/deepgram/types/delete_agent_configuration_v1response.py index 7adb31a8..84413ce4 100644 --- a/src/deepgram/types/delete_agent_configuration_v1response.py +++ b/src/deepgram/types/delete_agent_configuration_v1response.py @@ -3,3 +3,6 @@ import typing DeleteAgentConfigurationV1Response = typing.Dict[str, typing.Any] +""" +Confirmation that the agent configuration was deleted +""" diff --git a/src/deepgram/types/delete_agent_variable_v1response.py b/src/deepgram/types/delete_agent_variable_v1response.py index d4c1a33c..769f466f 100644 --- a/src/deepgram/types/delete_agent_variable_v1response.py +++ b/src/deepgram/types/delete_agent_variable_v1response.py @@ -3,3 +3,6 @@ import typing DeleteAgentVariableV1Response = typing.Dict[str, typing.Any] +""" +Confirmation that the agent variable was deleted +""" diff --git a/src/deepgram/types/listen_v1callback.py b/src/deepgram/types/listen_v1callback.py index a561c5f7..7b23103b 100644 --- a/src/deepgram/types/listen_v1callback.py +++ b/src/deepgram/types/listen_v1callback.py @@ -3,3 +3,6 @@ import typing ListenV1Callback = typing.Any +""" +URL to which we'll make the callback request +""" diff --git a/src/deepgram/types/listen_v1channels.py b/src/deepgram/types/listen_v1channels.py index 6c2d1dd1..9b968249 100644 --- a/src/deepgram/types/listen_v1channels.py +++ b/src/deepgram/types/listen_v1channels.py @@ -3,3 +3,6 @@ import typing ListenV1Channels = typing.Any +""" +The number of channels in the submitted audio +""" diff --git a/src/deepgram/types/listen_v1endpointing.py b/src/deepgram/types/listen_v1endpointing.py index 72097702..15ce646b 100644 --- a/src/deepgram/types/listen_v1endpointing.py +++ b/src/deepgram/types/listen_v1endpointing.py @@ -3,3 +3,6 @@ import typing ListenV1Endpointing = typing.Any +""" +Indicates how long Deepgram will wait to detect whether a speaker has finished speaking or pauses for a significant period of time. When set to a value, the streaming endpoint immediately finalizes the transcription for the processed time range and returns the transcript with a speech_final parameter set to true. Can also be set to false to disable endpointing +""" diff --git a/src/deepgram/types/listen_v1extra.py b/src/deepgram/types/listen_v1extra.py index e7ca9ae3..489a5856 100644 --- a/src/deepgram/types/listen_v1extra.py +++ b/src/deepgram/types/listen_v1extra.py @@ -3,3 +3,6 @@ import typing ListenV1Extra = typing.Any +""" +Arbitrary key-value pairs that are attached to the API response for usage in downstream processing +""" diff --git a/src/deepgram/types/listen_v1keyterm.py b/src/deepgram/types/listen_v1keyterm.py index 5bbffd49..67bd49f0 100644 --- a/src/deepgram/types/listen_v1keyterm.py +++ b/src/deepgram/types/listen_v1keyterm.py @@ -3,3 +3,6 @@ import typing ListenV1Keyterm = typing.Any +""" +Key term prompting can boost specialized terminology and brands. Only compatible with Nova-3 +""" diff --git a/src/deepgram/types/listen_v1keywords.py b/src/deepgram/types/listen_v1keywords.py index d5a5f7cf..7840c947 100644 --- a/src/deepgram/types/listen_v1keywords.py +++ b/src/deepgram/types/listen_v1keywords.py @@ -3,3 +3,6 @@ import typing ListenV1Keywords = typing.Any +""" +Keywords can boost or suppress specialized terminology and brands +""" diff --git a/src/deepgram/types/listen_v1language.py b/src/deepgram/types/listen_v1language.py index 78d7ad03..9bd0793c 100644 --- a/src/deepgram/types/listen_v1language.py +++ b/src/deepgram/types/listen_v1language.py @@ -3,3 +3,6 @@ import typing ListenV1Language = typing.Any +""" +The [BCP-47 language tag](https://tools.ietf.org/html/bcp47) that hints at the primary spoken language. Depending on the Model you choose only certain languages are available +""" diff --git a/src/deepgram/types/listen_v1mip_opt_out.py b/src/deepgram/types/listen_v1mip_opt_out.py index 1b548f7b..32550337 100644 --- a/src/deepgram/types/listen_v1mip_opt_out.py +++ b/src/deepgram/types/listen_v1mip_opt_out.py @@ -3,3 +3,6 @@ import typing ListenV1MipOptOut = typing.Any +""" +Opts out requests from the Deepgram Model Improvement Program. Refer to our Docs for pricing impacts before setting this to true. https://dpgr.am/deepgram-mip +""" diff --git a/src/deepgram/types/listen_v1replace.py b/src/deepgram/types/listen_v1replace.py index a1424264..ab90d2d6 100644 --- a/src/deepgram/types/listen_v1replace.py +++ b/src/deepgram/types/listen_v1replace.py @@ -3,3 +3,6 @@ import typing ListenV1Replace = typing.Any +""" +Search for terms or phrases in submitted audio and replaces them +""" diff --git a/src/deepgram/types/listen_v1request_file.py b/src/deepgram/types/listen_v1request_file.py index 936236a5..30148147 100644 --- a/src/deepgram/types/listen_v1request_file.py +++ b/src/deepgram/types/listen_v1request_file.py @@ -1,3 +1,6 @@ # This file was auto-generated by Fern from our API Definition. ListenV1RequestFile = bytes +""" +Binary audio file to transcribe +""" diff --git a/src/deepgram/types/listen_v1response_metadata.py b/src/deepgram/types/listen_v1response_metadata.py index 02b40254..974a9ecc 100644 --- a/src/deepgram/types/listen_v1response_metadata.py +++ b/src/deepgram/types/listen_v1response_metadata.py @@ -18,7 +18,7 @@ class ListenV1ResponseMetadata(UncheckedBaseModel): sha256: str created: dt.datetime duration: float - channels: float + channels: int models: typing.List[str] model_info: typing.Dict[str, typing.Any] summary_info: typing.Optional[ListenV1ResponseMetadataSummaryInfo] = None diff --git a/src/deepgram/types/listen_v1response_metadata_intents_info.py b/src/deepgram/types/listen_v1response_metadata_intents_info.py index a470c0a7..33de3488 100644 --- a/src/deepgram/types/listen_v1response_metadata_intents_info.py +++ b/src/deepgram/types/listen_v1response_metadata_intents_info.py @@ -9,8 +9,8 @@ class ListenV1ResponseMetadataIntentsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/deepgram/types/listen_v1response_metadata_sentiment_info.py b/src/deepgram/types/listen_v1response_metadata_sentiment_info.py index a78f9cc2..aa21aa8a 100644 --- a/src/deepgram/types/listen_v1response_metadata_sentiment_info.py +++ b/src/deepgram/types/listen_v1response_metadata_sentiment_info.py @@ -9,8 +9,8 @@ class ListenV1ResponseMetadataSentimentInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/deepgram/types/listen_v1response_metadata_summary_info.py b/src/deepgram/types/listen_v1response_metadata_summary_info.py index 7b4ea8ce..8ad3e8a7 100644 --- a/src/deepgram/types/listen_v1response_metadata_summary_info.py +++ b/src/deepgram/types/listen_v1response_metadata_summary_info.py @@ -9,8 +9,8 @@ class ListenV1ResponseMetadataSummaryInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/deepgram/types/listen_v1response_metadata_topics_info.py b/src/deepgram/types/listen_v1response_metadata_topics_info.py index 2569296b..bf4c3327 100644 --- a/src/deepgram/types/listen_v1response_metadata_topics_info.py +++ b/src/deepgram/types/listen_v1response_metadata_topics_info.py @@ -9,8 +9,8 @@ class ListenV1ResponseMetadataTopicsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/deepgram/types/listen_v1sample_rate.py b/src/deepgram/types/listen_v1sample_rate.py index ab4a2a92..1137bc7e 100644 --- a/src/deepgram/types/listen_v1sample_rate.py +++ b/src/deepgram/types/listen_v1sample_rate.py @@ -3,3 +3,6 @@ import typing ListenV1SampleRate = typing.Any +""" +Sample rate of submitted audio. Required (and only read) when a value is provided for encoding +""" diff --git a/src/deepgram/types/listen_v1search.py b/src/deepgram/types/listen_v1search.py index 4f31cb4d..84fcc4dd 100644 --- a/src/deepgram/types/listen_v1search.py +++ b/src/deepgram/types/listen_v1search.py @@ -3,3 +3,6 @@ import typing ListenV1Search = typing.Any +""" +Search for terms or phrases in submitted audio +""" diff --git a/src/deepgram/types/listen_v1tag.py b/src/deepgram/types/listen_v1tag.py index e8871d0d..5ef03be2 100644 --- a/src/deepgram/types/listen_v1tag.py +++ b/src/deepgram/types/listen_v1tag.py @@ -3,3 +3,6 @@ import typing ListenV1Tag = typing.Any +""" +Label your requests for the purpose of identification during usage reporting +""" diff --git a/src/deepgram/types/listen_v1utterance_end_ms.py b/src/deepgram/types/listen_v1utterance_end_ms.py index b774a294..d5580995 100644 --- a/src/deepgram/types/listen_v1utterance_end_ms.py +++ b/src/deepgram/types/listen_v1utterance_end_ms.py @@ -3,3 +3,6 @@ import typing ListenV1UtteranceEndMs = typing.Any +""" +Indicates how long Deepgram will wait to send an UtteranceEnd message after a word has been transcribed. Use with interim_results +""" diff --git a/src/deepgram/types/listen_v1version.py b/src/deepgram/types/listen_v1version.py index 2085b633..5e168fc5 100644 --- a/src/deepgram/types/listen_v1version.py +++ b/src/deepgram/types/listen_v1version.py @@ -3,3 +3,6 @@ import typing ListenV1Version = typing.Any +""" +Version of an AI model to use +""" diff --git a/src/deepgram/types/listen_v2eager_eot_threshold.py b/src/deepgram/types/listen_v2eager_eot_threshold.py index cd09e7fb..790f41df 100644 --- a/src/deepgram/types/listen_v2eager_eot_threshold.py +++ b/src/deepgram/types/listen_v2eager_eot_threshold.py @@ -3,3 +3,8 @@ import typing ListenV2EagerEotThreshold = typing.Any +""" +End-of-turn confidence required to fire an eager end-of-turn event. +When set, enables `EagerEndOfTurn` and `TurnResumed` events. Valid +Values 0.3 - 0.9. +""" diff --git a/src/deepgram/types/listen_v2eot_threshold.py b/src/deepgram/types/listen_v2eot_threshold.py index eb5d3887..c774974d 100644 --- a/src/deepgram/types/listen_v2eot_threshold.py +++ b/src/deepgram/types/listen_v2eot_threshold.py @@ -3,3 +3,7 @@ import typing ListenV2EotThreshold = typing.Any +""" +End-of-turn confidence required to finish a turn. Valid Values 0.5 - +0.9. +""" diff --git a/src/deepgram/types/listen_v2eot_timeout_ms.py b/src/deepgram/types/listen_v2eot_timeout_ms.py index 19a6924d..9f4c05c0 100644 --- a/src/deepgram/types/listen_v2eot_timeout_ms.py +++ b/src/deepgram/types/listen_v2eot_timeout_ms.py @@ -3,3 +3,7 @@ import typing ListenV2EotTimeoutMs = typing.Any +""" +A turn will be finished when this much time has passed after speech, +regardless of EOT confidence. +""" diff --git a/src/deepgram/types/listen_v2mip_opt_out.py b/src/deepgram/types/listen_v2mip_opt_out.py index 689450da..7582e9d1 100644 --- a/src/deepgram/types/listen_v2mip_opt_out.py +++ b/src/deepgram/types/listen_v2mip_opt_out.py @@ -3,3 +3,8 @@ import typing ListenV2MipOptOut = typing.Any +""" +Opts out requests from the Deepgram Model Improvement Program. Refer +to our Docs for pricing impacts before setting this to true. +https://dpgr.am/deepgram-mip +""" diff --git a/src/deepgram/types/listen_v2sample_rate.py b/src/deepgram/types/listen_v2sample_rate.py index 053a3e03..87c88643 100644 --- a/src/deepgram/types/listen_v2sample_rate.py +++ b/src/deepgram/types/listen_v2sample_rate.py @@ -3,3 +3,6 @@ import typing ListenV2SampleRate = typing.Any +""" +Sample rate of the audio stream in Hz. Required if sending non-containerized/raw audio. If sending containerized audio, this parameter should be omitted. +""" diff --git a/src/deepgram/types/listen_v2tag.py b/src/deepgram/types/listen_v2tag.py index 5a535a77..854799bd 100644 --- a/src/deepgram/types/listen_v2tag.py +++ b/src/deepgram/types/listen_v2tag.py @@ -3,3 +3,7 @@ import typing ListenV2Tag = typing.Any +""" +Label your requests for the purpose of identification during usage +reporting +""" 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 505c8115..4f080b78 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_intents_info.py @@ -9,8 +9,8 @@ class ReadV1ResponseMetadataMetadataIntentsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 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 b54f7b06..92b8fe78 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_sentiment_info.py @@ -9,8 +9,8 @@ class ReadV1ResponseMetadataMetadataSentimentInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 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 2f6a91c7..1c328afb 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_summary_info.py @@ -9,8 +9,8 @@ class ReadV1ResponseMetadataMetadataSummaryInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 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 8f413eb5..527915f7 100644 --- a/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py +++ b/src/deepgram/types/read_v1response_metadata_metadata_topics_info.py @@ -9,8 +9,8 @@ class ReadV1ResponseMetadataMetadataTopicsInfo(UncheckedBaseModel): model_uuid: typing.Optional[str] = None - input_tokens: typing.Optional[float] = None - output_tokens: typing.Optional[float] = None + input_tokens: typing.Optional[int] = None + output_tokens: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/deepgram/types/speak_v1mip_opt_out.py b/src/deepgram/types/speak_v1mip_opt_out.py index 80089874..c47fc133 100644 --- a/src/deepgram/types/speak_v1mip_opt_out.py +++ b/src/deepgram/types/speak_v1mip_opt_out.py @@ -3,3 +3,6 @@ import typing SpeakV1MipOptOut = typing.Any +""" +Opts out requests from the Deepgram Model Improvement Program. Refer to our Docs for pricing impacts before setting this to true. https://dpgr.am/deepgram-mip +""" diff --git a/src/deepgram/voice_agent/configurations/raw_client.py b/src/deepgram/voice_agent/configurations/raw_client.py index 6d2695a2..cb32f0ce 100644 --- a/src/deepgram/voice_agent/configurations/raw_client.py +++ b/src/deepgram/voice_agent/configurations/raw_client.py @@ -6,7 +6,8 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.request_options import RequestOptions from ...core.unchecked_base_model import construct_type from ...errors.bad_request_error import BadRequestError @@ -14,6 +15,7 @@ from ...types.create_agent_configuration_v1response import CreateAgentConfigurationV1Response from ...types.delete_agent_configuration_v1response import DeleteAgentConfigurationV1Response from ...types.list_agent_configurations_v1response import ListAgentConfigurationsV1Response +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -43,7 +45,7 @@ def list( A list of agent configurations """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents", + f"v1/projects/{encode_path_param(project_id)}/agents", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -72,6 +74,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -109,7 +115,7 @@ def create( Agent configuration created successfully """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents", + f"v1/projects/{encode_path_param(project_id)}/agents", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -147,6 +153,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -172,7 +182,7 @@ def get( An agent configuration """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -201,6 +211,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update( @@ -234,7 +248,7 @@ def update( Agent configuration updated """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="PUT", json={ @@ -270,6 +284,10 @@ def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -295,7 +313,7 @@ def delete( Agent configuration deleted """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -324,6 +342,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -351,7 +373,7 @@ async def list( A list of agent configurations """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents", + f"v1/projects/{encode_path_param(project_id)}/agents", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -380,6 +402,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -417,7 +443,7 @@ async def create( Agent configuration created successfully """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents", + f"v1/projects/{encode_path_param(project_id)}/agents", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -455,6 +481,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -480,7 +510,7 @@ async def get( An agent configuration """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -509,6 +539,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update( @@ -542,7 +576,7 @@ async def update( Agent configuration updated """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="PUT", json={ @@ -578,6 +612,10 @@ async def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -603,7 +641,7 @@ async def delete( Agent configuration deleted """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agents/{jsonable_encoder(agent_id)}", + f"v1/projects/{encode_path_param(project_id)}/agents/{encode_path_param(agent_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -632,4 +670,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/deepgram/voice_agent/variables/raw_client.py b/src/deepgram/voice_agent/variables/raw_client.py index 22294111..73f089ec 100644 --- a/src/deepgram/voice_agent/variables/raw_client.py +++ b/src/deepgram/voice_agent/variables/raw_client.py @@ -6,13 +6,15 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.request_options import RequestOptions from ...core.unchecked_base_model import construct_type from ...errors.bad_request_error import BadRequestError from ...types.agent_variable_v1 import AgentVariableV1 from ...types.delete_agent_variable_v1response import DeleteAgentVariableV1Response from ...types.list_agent_variables_v1response import ListAgentVariablesV1Response +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -42,7 +44,7 @@ def list( A list of agent variables """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables", + f"v1/projects/{encode_path_param(project_id)}/agent-variables", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -71,6 +73,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -107,7 +113,7 @@ def create( Agent variable created successfully """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables", + f"v1/projects/{encode_path_param(project_id)}/agent-variables", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -145,6 +151,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -170,7 +180,7 @@ def get( An agent variable """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -199,6 +209,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -224,7 +238,7 @@ def delete( Agent variable deleted """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -253,6 +267,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update( @@ -285,7 +303,7 @@ def update( Agent variable updated """ _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ @@ -321,6 +339,10 @@ def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -348,7 +370,7 @@ async def list( A list of agent variables """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables", + f"v1/projects/{encode_path_param(project_id)}/agent-variables", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -377,6 +399,10 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -413,7 +439,7 @@ async def create( Agent variable created successfully """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables", + f"v1/projects/{encode_path_param(project_id)}/agent-variables", base_url=self._client_wrapper.get_environment().base, method="POST", json={ @@ -451,6 +477,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -476,7 +506,7 @@ async def get( An agent variable """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, @@ -505,6 +535,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -530,7 +564,7 @@ async def delete( Agent variable deleted """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, @@ -559,6 +593,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update( @@ -591,7 +629,7 @@ async def update( Agent variable updated """ _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(project_id)}/agent-variables/{jsonable_encoder(variable_id)}", + f"v1/projects/{encode_path_param(project_id)}/agent-variables/{encode_path_param(variable_id)}", base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ @@ -627,4 +665,8 @@ async def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/tests/conftest.py b/tests/conftest.py index 36a95eaa..a74c554c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,6 +15,7 @@ import pytest _STARTED: bool = False +_EXTERNAL: bool = False # True when using an external WireMock instance (skip container lifecycle) _WIREMOCK_URL: str = "http://localhost:8080" # Default, will be updated after container starts _PROJECT_NAME: str = "deepgram-api" @@ -41,10 +42,19 @@ def _get_wiremock_port() -> str: def _start_wiremock() -> None: """Starts the WireMock container using docker-compose.""" - global _STARTED, _WIREMOCK_URL + global _STARTED, _EXTERNAL, _WIREMOCK_URL if _STARTED: return + # If WIREMOCK_URL is already set (e.g., by CI/CD pipeline), skip container management + existing_url = os.environ.get("WIREMOCK_URL") + if existing_url: + _WIREMOCK_URL = existing_url + _EXTERNAL = True + _STARTED = True + print(f"\nUsing external WireMock at {_WIREMOCK_URL} (container management skipped)") + return + print(f"\nStarting WireMock container (project: {_PROJECT_NAME})...") try: subprocess.run( @@ -65,6 +75,10 @@ def _start_wiremock() -> None: def _stop_wiremock() -> None: """Stops and removes the WireMock container.""" + if _EXTERNAL: + # Container is managed externally; nothing to tear down. + return + print("\nStopping WireMock container...") subprocess.run( ["docker", "compose", "-f", _COMPOSE_FILE, "-p", _PROJECT_NAME, "down", "-v"], @@ -83,6 +97,26 @@ def _is_xdist_worker(config: pytest.Config) -> bool: return hasattr(config, "workerinput") +def _has_httpx_aiohttp() -> bool: + """Check if httpx_aiohttp is importable.""" + try: + import httpx_aiohttp # type: ignore[import-not-found] # noqa: F401 + + return True + except ImportError: + return False + + +def pytest_collection_modifyitems(config: pytest.Config, items: list) -> None: + """Auto-skip @pytest.mark.aiohttp tests when httpx_aiohttp is not installed.""" + if _has_httpx_aiohttp(): + return + skip_aiohttp = pytest.mark.skip(reason="httpx_aiohttp not installed") + for item in items: + if "aiohttp" in item.keywords: + item.add_marker(skip_aiohttp) + + def pytest_configure(config: pytest.Config) -> None: """ Pytest hook that runs during test session setup. diff --git a/tests/test_aiohttp_autodetect.py b/tests/test_aiohttp_autodetect.py new file mode 100644 index 00000000..d7105914 --- /dev/null +++ b/tests/test_aiohttp_autodetect.py @@ -0,0 +1,116 @@ +import importlib +import sys +import unittest +from unittest import mock + +import httpx +import pytest + + +class TestMakeDefaultAsyncClientWithoutAiohttp(unittest.TestCase): + """Tests for _make_default_async_client when httpx_aiohttp is NOT installed.""" + + def test_returns_httpx_async_client(self) -> None: + """When httpx_aiohttp is not installed, returns plain httpx.AsyncClient.""" + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + from deepgram.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=True) + self.assertIsInstance(client, httpx.AsyncClient) + self.assertEqual(client.timeout.read, 60) + self.assertTrue(client.follow_redirects) + + def test_follow_redirects_none(self) -> None: + """When follow_redirects is None, omits it from httpx.AsyncClient.""" + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + from deepgram.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=None) + self.assertIsInstance(client, httpx.AsyncClient) + self.assertFalse(client.follow_redirects) + + def test_explicit_httpx_client_bypasses_autodetect(self) -> None: + """When user passes httpx_client explicitly, _make_default_async_client is not called.""" + + explicit_client = httpx.AsyncClient(timeout=120) + with mock.patch("deepgram.base_client._make_default_async_client") as mock_make: + # Replicate the generated conditional: httpx_client if httpx_client is not None else _make_default_async_client(...) + result = explicit_client if explicit_client is not None else mock_make(timeout=60, follow_redirects=True) + mock_make.assert_not_called() + self.assertIs(result, explicit_client) + + +@pytest.mark.aiohttp +class TestMakeDefaultAsyncClientWithAiohttp(unittest.TestCase): + """Tests for _make_default_async_client when httpx_aiohttp IS installed.""" + + def test_returns_aiohttp_client(self) -> None: + """When httpx_aiohttp is installed, returns HttpxAiohttpClient.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from deepgram.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=True) + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertEqual(client.timeout.read, 60) + self.assertTrue(client.follow_redirects) + + def test_follow_redirects_none(self) -> None: + """When httpx_aiohttp is installed and follow_redirects is None, omits it.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from deepgram.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=None) + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertFalse(client.follow_redirects) + + +class TestDefaultClientsWithoutAiohttp(unittest.TestCase): + """Tests for _default_clients.py convenience classes (no aiohttp).""" + + def test_default_async_httpx_client_defaults(self) -> None: + """DefaultAsyncHttpxClient applies SDK defaults.""" + from deepgram._default_clients import SDK_DEFAULT_TIMEOUT, DefaultAsyncHttpxClient + + client = DefaultAsyncHttpxClient() + self.assertIsInstance(client, httpx.AsyncClient) + self.assertEqual(client.timeout.read, SDK_DEFAULT_TIMEOUT) + self.assertTrue(client.follow_redirects) + + def test_default_async_httpx_client_overrides(self) -> None: + """DefaultAsyncHttpxClient allows overriding defaults.""" + from deepgram._default_clients import DefaultAsyncHttpxClient + + client = DefaultAsyncHttpxClient(timeout=30, follow_redirects=False) + self.assertEqual(client.timeout.read, 30) + self.assertFalse(client.follow_redirects) + + def test_default_aiohttp_client_raises_without_package(self) -> None: + """DefaultAioHttpClient raises RuntimeError when httpx_aiohttp not installed.""" + import deepgram._default_clients + + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + importlib.reload(deepgram._default_clients) + + with self.assertRaises(RuntimeError) as ctx: + deepgram._default_clients.DefaultAioHttpClient() + self.assertIn("pip install deepgram-sdk[aiohttp]", str(ctx.exception)) + + importlib.reload(deepgram._default_clients) + + +@pytest.mark.aiohttp +class TestDefaultClientsWithAiohttp(unittest.TestCase): + """Tests for _default_clients.py when httpx_aiohttp IS installed.""" + + def test_default_aiohttp_client_defaults(self) -> None: + """DefaultAioHttpClient works when httpx_aiohttp is installed.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from deepgram._default_clients import SDK_DEFAULT_TIMEOUT, DefaultAioHttpClient + + client = DefaultAioHttpClient() + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertEqual(client.timeout.read, SDK_DEFAULT_TIMEOUT) + self.assertTrue(client.follow_redirects) diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py index 7a76f285..fae0e0df 100644 --- a/tests/utils/test_http_client.py +++ b/tests/utils/test_http_client.py @@ -1,7 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from typing import Any, Dict +from unittest.mock import AsyncMock, MagicMock, patch +import httpx import pytest from deepgram.core.http_client import ( @@ -298,3 +300,363 @@ def test_preserves_base_url_path_prefix_trailing_slash() -> None: """Test that path prefixes in base URL are preserved.""" result = _build_url("https://cloud.example.com/org/tenant/api/", "/users") assert result == "https://cloud.example.com/org/tenant/api/users" + + +# --------------------------------------------------------------------------- +# Connection error retry tests +# --------------------------------------------------------------------------- + + +def _make_sync_http_client(mock_client: Any) -> HttpClient: + return HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + ) + + +def _make_async_http_client(mock_client: Any) -> AsyncHttpClient: + return AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + async_base_headers=None, + ) + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_retries_on_connect_error(mock_sleep: MagicMock) -> None: + """Sync: connection error retries on httpx.ConnectError.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + http_client = _make_sync_http_client(mock_client) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_retries_on_remote_protocol_error(mock_sleep: MagicMock) -> None: + """Sync: connection error retries on httpx.RemoteProtocolError.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.RemoteProtocolError("Remote end closed connection without response"), + _DummyResponse(), + ] + http_client = _make_sync_http_client(mock_client) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_connection_error_exhausts_retries(mock_sleep: MagicMock) -> None: + """Sync: connection error exhausts retries then raises.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = _make_sync_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + assert mock_sleep.call_count == 2 + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_connection_error_respects_max_retries_zero(mock_sleep: MagicMock) -> None: + """Sync: connection error respects max_retries=0.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = _make_sync_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 0}, + ) + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_retries_on_connect_error(mock_sleep: AsyncMock) -> None: + """Async: connection error retries on httpx.ConnectError.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + ) + http_client = _make_async_http_client(mock_client) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_retries_on_remote_protocol_error(mock_sleep: AsyncMock) -> None: + """Async: connection error retries on httpx.RemoteProtocolError.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.RemoteProtocolError("Remote end closed connection without response"), + _DummyResponse(), + ] + ) + http_client = _make_async_http_client(mock_client) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_connection_error_exhausts_retries(mock_sleep: AsyncMock) -> None: + """Async: connection error exhausts retries then raises.""" + mock_client = MagicMock() + mock_client.request = AsyncMock(side_effect=httpx.ConnectError("connection failed")) + http_client = _make_async_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + await http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + assert mock_sleep.call_count == 2 + + +# --------------------------------------------------------------------------- +# base_max_retries constructor parameter tests +# --------------------------------------------------------------------------- + + +def test_sync_http_client_default_base_max_retries() -> None: + """HttpClient defaults to base_max_retries=2.""" + http_client = HttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + ) + assert http_client.base_max_retries == 2 + + +def test_async_http_client_default_base_max_retries() -> None: + """AsyncHttpClient defaults to base_max_retries=2.""" + http_client = AsyncHttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + ) + assert http_client.base_max_retries == 2 + + +def test_sync_http_client_custom_base_max_retries() -> None: + """HttpClient accepts a custom base_max_retries value.""" + http_client = HttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_max_retries=5, + ) + assert http_client.base_max_retries == 5 + + +def test_async_http_client_custom_base_max_retries() -> None: + """AsyncHttpClient accepts a custom base_max_retries value.""" + http_client = AsyncHttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_max_retries=5, + ) + assert http_client.base_max_retries == 5 + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_base_max_retries_zero_disables_retries(mock_sleep: MagicMock) -> None: + """Sync: base_max_retries=0 disables retries when no request_options override.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, + ) + + with pytest.raises(httpx.ConnectError): + http_client.request(path="/test", method="GET") + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_base_max_retries_zero_disables_retries(mock_sleep: AsyncMock) -> None: + """Async: base_max_retries=0 disables retries when no request_options override.""" + mock_client = MagicMock() + mock_client.request = AsyncMock(side_effect=httpx.ConnectError("connection failed")) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, + ) + + with pytest.raises(httpx.ConnectError): + await http_client.request(path="/test", method="GET") + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_request_options_override_base_max_retries(mock_sleep: MagicMock) -> None: + """Sync: request_options max_retries overrides base_max_retries.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("connection failed"), + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, # base says no retries + ) + + # But request_options overrides to allow 2 retries + response = http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + assert response.status_code == 200 + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_request_options_override_base_max_retries(mock_sleep: AsyncMock) -> None: + """Async: request_options max_retries overrides base_max_retries.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("connection failed"), + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + ) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, # base says no retries + ) + + # But request_options overrides to allow 2 retries + response = await http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + assert response.status_code == 200 + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + + +@patch("deepgram.core.http_client.time.sleep", return_value=None) +def test_sync_base_max_retries_used_as_default(mock_sleep: MagicMock) -> None: + """Sync: base_max_retries is used when request_options has no max_retries.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + _DummyResponse(), + ] + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=3, + ) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + # 1 initial + 3 retries = 4 total attempts + assert mock_client.request.call_count == 4 + + +@pytest.mark.asyncio +@patch("deepgram.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_base_max_retries_used_as_default(mock_sleep: AsyncMock) -> None: + """Async: base_max_retries is used when request_options has no max_retries.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + _DummyResponse(), + ] + ) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=3, + ) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + # 1 initial + 3 retries = 4 total attempts + assert mock_client.request.call_count == 4 diff --git a/tests/wire/conftest.py b/tests/wire/conftest.py index d138641f..dcbbbfb1 100644 --- a/tests/wire/conftest.py +++ b/tests/wire/conftest.py @@ -61,7 +61,7 @@ def verify_request_count( test_id: str, method: str, url_path: str, - query_params: Optional[Dict[str, str]], + query_params: Optional[Dict[str, Any]], expected: int, ) -> None: """Verifies the number of requests made to WireMock filtered by test ID for concurrency safety.""" @@ -72,7 +72,12 @@ def verify_request_count( "headers": {"X-Test-Id": {"equalTo": test_id}}, } if query_params: - query_parameters = {k: {"equalTo": v} for k, v in query_params.items()} + query_parameters = {} + for k, v in query_params.items(): + if isinstance(v, list): + query_parameters[k] = {"hasExactly": [{"equalTo": item} for item in v]} + else: + query_parameters[k] = {"equalTo": v} request_body["queryParameters"] = query_parameters response = httpx.post(f"{wiremock_admin_url}/requests/find", json=request_body) assert response.status_code == 200, "Failed to query WireMock requests" diff --git a/tests/wire/test_listen_v1_media.py b/tests/wire/test_listen_v1_media.py index 8c08f1ab..af68c86c 100644 --- a/tests/wire/test_listen_v1_media.py +++ b/tests/wire/test_listen_v1_media.py @@ -24,6 +24,7 @@ def test_listen_v1_media_transcribe_url() -> None: dictation=True, encoding="linear16", filler_words=True, + keyterm=["keyterm"], keywords=["keywords"], language="language", measurements=True, @@ -66,6 +67,7 @@ def test_listen_v1_media_transcribe_url() -> None: "dictation": "true", "encoding": "linear16", "filler_words": "true", + "keyterm": "keyterm", "keywords": "keywords", "language": "language", "measurements": "true", diff --git a/tests/wire/test_manage_v1_projects_billing_breakdown.py b/tests/wire/test_manage_v1_projects_billing_breakdown.py index 5871b466..8417a270 100644 --- a/tests/wire/test_manage_v1_projects_billing_breakdown.py +++ b/tests/wire/test_manage_v1_projects_billing_breakdown.py @@ -13,6 +13,7 @@ def test_manage_v1_projects_billing_breakdown_list_() -> None: deployment="hosted", tag="tag1", line_item="streaming::nova-3", + grouping=["deployment", "line_item"], ) verify_request_count( test_id, @@ -25,6 +26,7 @@ def test_manage_v1_projects_billing_breakdown_list_() -> None: "deployment": "hosted", "tag": "tag1", "line_item": "streaming::nova-3", + "grouping": ["deployment", "line_item"], }, 1, ) diff --git a/tests/wire/test_selfHosted_v1_distributionCredentials.py b/tests/wire/test_selfHosted_v1_distributionCredentials.py index 5bf736d2..414897a5 100644 --- a/tests/wire/test_selfHosted_v1_distributionCredentials.py +++ b/tests/wire/test_selfHosted_v1_distributionCredentials.py @@ -19,13 +19,14 @@ def test_selfHosted_v1_distributionCredentials_create() -> None: client = get_client(test_id) client.self_hosted.v1.distribution_credentials.create( project_id="123456-7890-1234-5678-901234", + scopes=["self-hosted:products"], provider="quay", ) verify_request_count( test_id, "POST", "/v1/projects/123456-7890-1234-5678-901234/self-hosted/distribution/credentials", - {"provider": "quay"}, + {"scopes": "self-hosted:products", "provider": "quay"}, 1, ) diff --git a/wiremock/wiremock-mappings.json b/wiremock/wiremock-mappings.json index 05e23bc8..92f87270 100644 --- a/wiremock/wiremock-mappings.json +++ b/wiremock/wiremock-mappings.json @@ -1 +1,2326 @@ -{"mappings": [{"id": "533b5d52-ab21-4763-aaae-87cf52f49aa5", "name": "List Agent Think Models - default", "request": {"urlPathTemplate": "/v1/agent/settings/think/models", "method": "GET"}, "response": {"status": 200, "body": "{\n \"models\": [\n {\n \"id\": \"gpt-5\",\n \"name\": \"name\",\n \"provider\": \"open_ai\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "533b5d52-ab21-4763-aaae-87cf52f49aa5", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}, "postServeActions": []}, {"id": "20e1029e-8bb9-4092-a809-b943e60822ef", "name": "Token-based Authentication - default", "request": {"urlPathTemplate": "/v1/auth/grant", "method": "POST"}, "response": {"status": 200, "body": "{\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U\",\n \"expires_in\": 30\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "20e1029e-8bb9-4092-a809-b943e60822ef", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "49d8d51a-7f01-4598-804f-b6f54cdc22da", "name": "Transcribe and analyze pre-recorded audio and video - default", "request": {"urlPathTemplate": "/v1/listen", "method": "POST", "queryParameters": {"callback": {"equalTo": "callback"}, "callback_method": {"equalTo": "POST"}, "extra": {"equalTo": "extra"}, "sentiment": {"equalTo": "true"}, "summarize": {"equalTo": "v2"}, "tag": {"equalTo": "tag"}, "topics": {"equalTo": "true"}, "custom_topic": {"equalTo": "custom_topic"}, "custom_topic_mode": {"equalTo": "extended"}, "intents": {"equalTo": "true"}, "custom_intent": {"equalTo": "custom_intent"}, "custom_intent_mode": {"equalTo": "extended"}, "detect_entities": {"equalTo": "true"}, "detect_language": {"equalTo": "true"}, "diarize": {"equalTo": "true"}, "dictation": {"equalTo": "true"}, "encoding": {"equalTo": "linear16"}, "filler_words": {"equalTo": "true"}, "keywords": {"equalTo": "keywords"}, "language": {"equalTo": "language"}, "measurements": {"equalTo": "true"}, "model": {"equalTo": "nova-3"}, "multichannel": {"equalTo": "true"}, "numerals": {"equalTo": "true"}, "paragraphs": {"equalTo": "true"}, "profanity_filter": {"equalTo": "true"}, "punctuate": {"equalTo": "true"}, "redact": {"equalTo": "redact"}, "replace": {"equalTo": "replace"}, "search": {"equalTo": "search"}, "smart_format": {"equalTo": "true"}, "utterances": {"equalTo": "true"}, "utt_split": {"equalTo": "1.1"}, "version": {"equalTo": "latest"}, "mip_opt_out": {"equalTo": "true"}}}, "response": {"status": 200, "body": "{\n \"metadata\": {\n \"request_id\": \"a847f427-4ad5-4d67-9b95-db801e58251c\",\n \"sha256\": \"154e291ecfa8be6ab8343560bcc109008fa7853eb5372533e8efdefc9b504c33\",\n \"created\": \"2024-05-12T18:57:13Z\",\n \"duration\": 25.933313,\n \"channels\": 1,\n \"models\": [\n \"30089e05-99d1-4376-b32e-c263170674af\"\n ],\n \"model_info\": {\n \"30089e05-99d1-4376-b32e-c263170674af\": {\n \"name\": \"2-general-nova\",\n \"version\": \"2024-01-09.29447\",\n \"arch\": \"nova-2\"\n }\n },\n \"summary_info\": {\n \"model_uuid\": \"67875a7f-c9c4-48a0-aa55-5bdb8a91c34a\",\n \"input_tokens\": 95,\n \"output_tokens\": 63\n },\n \"sentiment_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 105\n },\n \"topics_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 7\n },\n \"intents_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 4\n },\n \"tags\": [\n \"test\"\n ]\n },\n \"results\": {\n \"channels\": [\n {}\n ],\n \"utterances\": [\n {}\n ],\n \"summary\": {\n \"result\": \"success\",\n \"short\": \"Speaker 0 discusses the significance of the first all-female spacewalk with an all-female team, stating that it is a tribute to the skilled and qualified women who were denied opportunities in the past.\"\n },\n \"topics\": {\n \"results\": {\n \"topics\": {\n \"segments\": [\n {\n \"text\": \"And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 32,\n \"end_word\": 69,\n \"topics\": [\n {\n \"topic\": \"Spacewalk\",\n \"confidence_score\": 0.91581345\n }\n ]\n }\n ]\n }\n }\n },\n \"intents\": {\n \"results\": {\n \"intents\": {\n \"segments\": [\n {\n \"text\": \"If you found this valuable, you can subscribe to the show on spotify or your favorite podcast app.\",\n \"start_word\": 354,\n \"end_word\": 414,\n \"intents\": [\n {\n \"intent\": \"Encourage podcasting\",\n \"confidence_score\": 0.0038975573\n }\n ]\n }\n ]\n }\n }\n },\n \"sentiments\": {\n \"segments\": [\n {\n \"text\": \"Yeah. As as much as, um, it's worth celebrating, uh, the first, uh, spacewalk, um, with an all-female team, I think many of us are looking forward to it just being normal. And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 0,\n \"end_word\": 69,\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810546875\n }\n ],\n \"average\": {\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810185185185185\n }\n }\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "49d8d51a-7f01-4598-804f-b6f54cdc22da", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "0a0be61b-f024-4120-9c54-23bca3e07c93", "name": "List Models - default", "request": {"urlPathTemplate": "/v1/models", "method": "GET", "queryParameters": {"include_outdated": {"equalTo": "true"}}}, "response": {"status": 200, "body": "{\n \"stt\": [\n {\n \"name\": \"nova-3\",\n \"canonical_name\": \"nova-3\",\n \"architecture\": \"base\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2021-11-10.1\",\n \"uuid\": \"6b28e919-8427-4f32-9847-492e2efd7daf\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": true\n }\n ],\n \"tts\": [\n {\n \"name\": \"zeus\",\n \"canonical_name\": \"aura-2-zeus-en\",\n \"architecture\": \"aura-2\",\n \"languages\": [\n \"en\",\n \"en-US\"\n ],\n \"version\": \"2025-04-07.0\",\n \"uuid\": \"2baf189d-91ac-481d-b6d1-750888667b31\",\n \"metadata\": {\n \"accent\": \"American\",\n \"age\": \"Adult\",\n \"color\": \"#C58DFF\",\n \"image\": \"https://static.deepgram.com/examples/avatars/zeus.jpg\",\n \"sample\": \"https://static.deepgram.com/examples/Aura-2-zeus.wav\",\n \"tags\": [\n \"masculine\",\n \"deep\",\n \"trustworthy\",\n \"smooth\"\n ],\n \"use_cases\": [\n \"IVR\"\n ]\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "0a0be61b-f024-4120-9c54-23bca3e07c93", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}, "postServeActions": []}, {"id": "0f94d3ea-43b6-4a1a-bce4-ab05b85440ae", "name": "Get a specific Model - default", "request": {"urlPathTemplate": "/v1/models/{model_id}", "method": "GET", "pathParameters": {"model_id": {"equalTo": "af6e9977-99f6-4d8f-b6f5-dfdf6fb6e291"}}}, "response": {"status": 200, "body": "{\n \"name\": \"general\",\n \"canonical_name\": \"enhanced-general\",\n \"architecture\": \"polaris\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2022-05-18.1\",\n \"uuid\": \"c7226e9e-ae1c-4057-ae2a-a71a6b0dc588\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": false\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "0f94d3ea-43b6-4a1a-bce4-ab05b85440ae", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "d08cac56-bc4d-4756-8fd1-d508914334d5", "name": "List Projects - default", "request": {"urlPathTemplate": "/v1/projects", "method": "GET"}, "response": {"status": 200, "body": "{\n \"projects\": [\n {\n \"project_id\": \"project_id\",\n \"name\": \"name\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "d08cac56-bc4d-4756-8fd1-d508914334d5", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}, "postServeActions": []}, {"id": "6f0163a8-530c-4e25-bbe0-9ca86b9525dc", "name": "Get a Project - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"limit": {"equalTo": "1.1"}, "page": {"equalTo": "1.1"}}}, "response": {"status": 200, "body": "{\n \"project_id\": \"project_id\",\n \"mip_opt_out\": true,\n \"name\": \"name\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "6f0163a8-530c-4e25-bbe0-9ca86b9525dc", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "68918577-6401-4439-8533-356257ff7bcf", "name": "Delete a Project - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "68918577-6401-4439-8533-356257ff7bcf", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "659fc38b-3934-4e43-93bf-d331f547449e", "name": "Update a Project - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}", "method": "PATCH", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"Successfully updated project info.\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "659fc38b-3934-4e43-93bf-d331f547449e", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "43ae6622-ad2f-4c81-9bc9-a8bbe17ef9d8", "name": "Leave a Project - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/leave", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "43ae6622-ad2f-4c81-9bc9-a8bbe17ef9d8", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "032d9b1c-3b87-40fb-bfab-8c5be92a5d71", "name": "List Project Keys - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/keys", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"status": {"equalTo": "active"}}}, "response": {"status": 200, "body": "{\n \"api_keys\": [\n {\n \"member\": {\n \"member_id\": \"1000-2000-3000-4000\",\n \"email\": \"john@test.com\"\n },\n \"api_key\": {\n \"api_key_id\": \"1234567890abcdef1234567890abcdef\",\n \"comment\": \"A comment\",\n \"scopes\": [\n \"admin\"\n ],\n \"created\": \"2021-01-01T00:00:00Z\"\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "032d9b1c-3b87-40fb-bfab-8c5be92a5d71", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "0167c735-0b6f-4715-8df8-32300d4dae72", "name": "Create a Project Key - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/keys", "method": "POST", "pathParameters": {"project_id": {"equalTo": "project_id"}}}, "response": {"status": 200, "body": "{\n \"api_key_id\": \"api_key_id\",\n \"key\": \"key\",\n \"comment\": \"comment\",\n \"scopes\": [\n \"scopes\",\n \"scopes\"\n ],\n \"tags\": [\n \"tags\",\n \"tags\"\n ],\n \"expiration_date\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "0167c735-0b6f-4715-8df8-32300d4dae72", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "c9812dd3-f87e-4798-aec3-af0933330dd5", "name": "Get a Project Key - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/keys/{key_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "key_id": {"equalTo": "123456789012345678901234"}}}, "response": {"status": 200, "body": "{\n \"item\": {\n \"member\": {\n \"member_id\": \"1000-2000-3000-4000\",\n \"email\": \"john@test.com\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"api_key\": {\n \"api_key_id\": \"1000-2000-3000-4000\",\n \"comment\": \"A comment\",\n \"scopes\": [\n \"admin\"\n ],\n \"tags\": [\n \"prod\",\n \"west-region\"\n ],\n \"expiration_date\": \"2021-01-01T00:00:00Z\",\n \"created\": \"2021-01-01T00:00:00Z\"\n }\n }\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "c9812dd3-f87e-4798-aec3-af0933330dd5", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "3d2fbc7c-7bac-436f-a6ac-abe1b2c2caac", "name": "Delete a Project Key - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/keys/{key_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "key_id": {"equalTo": "123456789012345678901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "3d2fbc7c-7bac-436f-a6ac-abe1b2c2caac", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "91e103d5-72f7-463d-840d-310069e33de9", "name": "List Project Members - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/members", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"members\": [\n {\n \"member_id\": \"member_id\",\n \"email\": \"email\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "91e103d5-72f7-463d-840d-310069e33de9", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "515c6f7e-09c3-43ea-ad6c-65bc11d20f46", "name": "Delete a Project Member - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "member_id": {"equalTo": "123456789012345678901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "515c6f7e-09c3-43ea-ad6c-65bc11d20f46", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "a920ad0e-2796-4361-ac16-ac83fb75e32a", "name": "List Project Models - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/models", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"include_outdated": {"equalTo": "true"}}}, "response": {"status": 200, "body": "{\n \"stt\": [\n {\n \"name\": \"nova-3\",\n \"canonical_name\": \"nova-3\",\n \"architecture\": \"base\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2021-11-10.1\",\n \"uuid\": \"6b28e919-8427-4f32-9847-492e2efd7daf\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": true\n }\n ],\n \"tts\": [\n {\n \"name\": \"zeus\",\n \"canonical_name\": \"aura-2-zeus-en\",\n \"architecture\": \"aura-2\",\n \"languages\": [\n \"en\",\n \"en-US\"\n ],\n \"version\": \"2025-04-07.0\",\n \"uuid\": \"2baf189d-91ac-481d-b6d1-750888667b31\",\n \"metadata\": {\n \"accent\": \"American\",\n \"age\": \"Adult\",\n \"color\": \"#C58DFF\",\n \"image\": \"https://static.deepgram.com/examples/avatars/zeus.jpg\",\n \"sample\": \"https://static.deepgram.com/examples/Aura-2-zeus.wav\",\n \"tags\": [\n \"masculine\",\n \"deep\",\n \"trustworthy\",\n \"smooth\"\n ],\n \"use_cases\": [\n \"IVR\"\n ]\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "a920ad0e-2796-4361-ac16-ac83fb75e32a", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "9f8c6bf2-ebee-4956-b39f-0291b9d64b6e", "name": "Get a Project Model - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/models/{model_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "model_id": {"equalTo": "af6e9977-99f6-4d8f-b6f5-dfdf6fb6e291"}}}, "response": {"status": 200, "body": "{\n \"name\": \"general\",\n \"canonical_name\": \"enhanced-general\",\n \"architecture\": \"polaris\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2022-05-18.1\",\n \"uuid\": \"c7226e9e-ae1c-4057-ae2a-a71a6b0dc588\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": false\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "9f8c6bf2-ebee-4956-b39f-0291b9d64b6e", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "d6a14959-05fa-4aec-9f0c-ba2a817c66e5", "name": "List Project Requests - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/requests", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "2024-01-15T09:30:00Z"}, "end": {"equalTo": "2024-01-15T09:30:00Z"}, "limit": {"equalTo": "1.1"}, "page": {"equalTo": "1.1"}, "accessor": {"equalTo": "12345678-1234-1234-1234-123456789012"}, "request_id": {"equalTo": "12345678-1234-1234-1234-123456789012"}, "deployment": {"equalTo": "hosted"}, "endpoint": {"equalTo": "listen"}, "method": {"equalTo": "sync"}, "status": {"equalTo": "succeeded"}}}, "response": {"status": 200, "body": "{\n \"page\": 1.1,\n \"limit\": 1.1,\n \"requests\": [\n {\n \"request_id\": \"request_id\",\n \"project_uuid\": \"project_uuid\",\n \"created\": \"2024-01-15T09:30:00Z\",\n \"path\": \"path\",\n \"api_key_id\": \"api_key_id\",\n \"response\": {\n \"key\": \"value\"\n },\n \"code\": 1.1,\n \"deployment\": \"deployment\",\n \"callback\": \"callback\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "d6a14959-05fa-4aec-9f0c-ba2a817c66e5", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "733e39aa-d3ef-4ea7-8062-af080c6288c4", "name": "Get a Project Request - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/requests/{request_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "request_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"request\": {\n \"request_id\": \"request_id\",\n \"project_uuid\": \"project_uuid\",\n \"created\": \"2024-01-15T09:30:00Z\",\n \"path\": \"path\",\n \"api_key_id\": \"api_key_id\",\n \"response\": {\n \"key\": \"value\"\n },\n \"code\": 1.1,\n \"deployment\": \"deployment\",\n \"callback\": \"callback\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "733e39aa-d3ef-4ea7-8062-af080c6288c4", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "6309dd55-c993-4ce1-b0b2-01a41c9f08d6", "name": "Get Project Usage - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/usage", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "start"}, "end": {"equalTo": "end"}, "accessor": {"equalTo": "12345678-1234-1234-1234-123456789012"}, "alternatives": {"equalTo": "true"}, "callback_method": {"equalTo": "true"}, "callback": {"equalTo": "true"}, "channels": {"equalTo": "true"}, "custom_intent_mode": {"equalTo": "true"}, "custom_intent": {"equalTo": "true"}, "custom_topic_mode": {"equalTo": "true"}, "custom_topic": {"equalTo": "true"}, "deployment": {"equalTo": "hosted"}, "detect_entities": {"equalTo": "true"}, "detect_language": {"equalTo": "true"}, "diarize": {"equalTo": "true"}, "dictation": {"equalTo": "true"}, "encoding": {"equalTo": "true"}, "endpoint": {"equalTo": "listen"}, "extra": {"equalTo": "true"}, "filler_words": {"equalTo": "true"}, "intents": {"equalTo": "true"}, "keyterm": {"equalTo": "true"}, "keywords": {"equalTo": "true"}, "language": {"equalTo": "true"}, "measurements": {"equalTo": "true"}, "method": {"equalTo": "sync"}, "model": {"equalTo": "6f548761-c9c0-429a-9315-11a1d28499c8"}, "multichannel": {"equalTo": "true"}, "numerals": {"equalTo": "true"}, "paragraphs": {"equalTo": "true"}, "profanity_filter": {"equalTo": "true"}, "punctuate": {"equalTo": "true"}, "redact": {"equalTo": "true"}, "replace": {"equalTo": "true"}, "sample_rate": {"equalTo": "true"}, "search": {"equalTo": "true"}, "sentiment": {"equalTo": "true"}, "smart_format": {"equalTo": "true"}, "summarize": {"equalTo": "true"}, "tag": {"equalTo": "tag1"}, "topics": {"equalTo": "true"}, "utt_split": {"equalTo": "true"}, "utterances": {"equalTo": "true"}, "version": {"equalTo": "true"}}}, "response": {"status": 200, "body": "{\n \"start\": \"2024-10-16\",\n \"end\": \"2024-10-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "6309dd55-c993-4ce1-b0b2-01a41c9f08d6", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "b132121b-4efe-42ad-a268-8acac35c189b", "name": "Get Project Balances - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/balances", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"balances\": [\n {\n \"balance_id\": \"balance_id\",\n \"amount\": 1.1,\n \"units\": \"units\",\n \"purchase_order_id\": \"purchase_order_id\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "b132121b-4efe-42ad-a268-8acac35c189b", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "4019c244-52d3-4d57-902c-af837631650a", "name": "Get a Project Balance - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/balances/{balance_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "balance_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"balance_id\": \"balance_id\",\n \"amount\": 1.1,\n \"units\": \"units\",\n \"purchase_order_id\": \"purchase_order_id\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "4019c244-52d3-4d57-902c-af837631650a", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "555b6751-587f-400c-bf5e-400e108ad6b4", "name": "Get Project Billing Breakdown - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/billing/breakdown", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "start"}, "end": {"equalTo": "end"}, "accessor": {"equalTo": "12345678-1234-1234-1234-123456789012"}, "deployment": {"equalTo": "hosted"}, "tag": {"equalTo": "tag1"}, "line_item": {"equalTo": "streaming::nova-3"}}}, "response": {"status": 200, "body": "{\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n },\n \"results\": [\n {\n \"dollars\": 0.25,\n \"grouping\": {\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-16\",\n \"accessor\": \"123456789012345678901234\",\n \"deployment\": \"hosted\",\n \"line_item\": \"streaming::nova-3\",\n \"tags\": [\n \"tag1\",\n \"tag2\"\n ]\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "555b6751-587f-400c-bf5e-400e108ad6b4", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "a61ae38c-e41f-4726-a55c-88f2135897be", "name": "List Project Billing Fields - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/billing/fields", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "start"}, "end": {"equalTo": "end"}}}, "response": {"status": 200, "body": "{\n \"accessors\": [\n \"12345678-1234-1234-1234-123456789012\",\n \"87654321-4321-4321-4321-210987654321\"\n ],\n \"deployments\": [\n \"hosted\",\n \"self-hosted\"\n ],\n \"tags\": [\n \"dev\",\n \"production\"\n ],\n \"line_items\": {\n \"streaming::nova-3\": \"Nova - 3 (Stream)\",\n \"sync::aura-2\": \"Aura -2 (Sync)\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "a61ae38c-e41f-4726-a55c-88f2135897be", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "85b4373c-ba39-41b1-84e8-ae1ee6b180ca", "name": "List Project Purchases - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/purchases", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"limit": {"equalTo": "1.1"}}}, "response": {"status": 200, "body": "{\n \"orders\": [\n {\n \"order_id\": \"025e19ba-b6d9-4a04-9f99-4fe715aca5f1\",\n \"expiration\": \"2026-03-04T00:00:00Z\",\n \"created\": \"2023-02-21T21:13:40Z\",\n \"amount\": 150,\n \"units\": \"usd\",\n \"order_type\": \"promotional\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "85b4373c-ba39-41b1-84e8-ae1ee6b180ca", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "2dd14c67-ed4e-4d97-9636-0a712899deb8", "name": "List Project Invites - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/invites", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"invites\": [\n {\n \"email\": \"email\",\n \"scope\": \"scope\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "2dd14c67-ed4e-4d97-9636-0a712899deb8", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "7c109496-adfe-4e85-b007-a6f799ee95cb", "name": "Create a Project Invite - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/invites", "method": "POST", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "7c109496-adfe-4e85-b007-a6f799ee95cb", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "d6d268d0-d91e-4a65-80e0-339621173db9", "name": "Delete a Project Invite - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/invites/{email}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "email": {"equalTo": "john.doe@example.com"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "d6d268d0-d91e-4a65-80e0-339621173db9", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "1b965d71-c930-4a0b-90f3-2289f80f3634", "name": "List Project Member Scopes - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}/scopes", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "member_id": {"equalTo": "123456789012345678901234"}}}, "response": {"status": 200, "body": "{\n \"scopes\": [\n \"scopes\"\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "1b965d71-c930-4a0b-90f3-2289f80f3634", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "eb2f5de2-b887-47be-abd5-7cb702aca55d", "name": "Update Project Member Scopes - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}/scopes", "method": "PUT", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "member_id": {"equalTo": "123456789012345678901234"}}}, "response": {"status": 200, "body": "{\n \"message\": \"message\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "eb2f5de2-b887-47be-abd5-7cb702aca55d", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "9bdf51a4-1e10-41b8-8de2-2df650562db3", "name": "Get Project Usage Breakdown - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/usage/breakdown", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "start"}, "end": {"equalTo": "end"}, "grouping": {"equalTo": "accessor"}, "accessor": {"equalTo": "12345678-1234-1234-1234-123456789012"}, "alternatives": {"equalTo": "true"}, "callback_method": {"equalTo": "true"}, "callback": {"equalTo": "true"}, "channels": {"equalTo": "true"}, "custom_intent_mode": {"equalTo": "true"}, "custom_intent": {"equalTo": "true"}, "custom_topic_mode": {"equalTo": "true"}, "custom_topic": {"equalTo": "true"}, "deployment": {"equalTo": "hosted"}, "detect_entities": {"equalTo": "true"}, "detect_language": {"equalTo": "true"}, "diarize": {"equalTo": "true"}, "dictation": {"equalTo": "true"}, "encoding": {"equalTo": "true"}, "endpoint": {"equalTo": "listen"}, "extra": {"equalTo": "true"}, "filler_words": {"equalTo": "true"}, "intents": {"equalTo": "true"}, "keyterm": {"equalTo": "true"}, "keywords": {"equalTo": "true"}, "language": {"equalTo": "true"}, "measurements": {"equalTo": "true"}, "method": {"equalTo": "sync"}, "model": {"equalTo": "6f548761-c9c0-429a-9315-11a1d28499c8"}, "multichannel": {"equalTo": "true"}, "numerals": {"equalTo": "true"}, "paragraphs": {"equalTo": "true"}, "profanity_filter": {"equalTo": "true"}, "punctuate": {"equalTo": "true"}, "redact": {"equalTo": "true"}, "replace": {"equalTo": "true"}, "sample_rate": {"equalTo": "true"}, "search": {"equalTo": "true"}, "sentiment": {"equalTo": "true"}, "smart_format": {"equalTo": "true"}, "summarize": {"equalTo": "true"}, "tag": {"equalTo": "tag1"}, "topics": {"equalTo": "true"}, "utt_split": {"equalTo": "true"}, "utterances": {"equalTo": "true"}, "version": {"equalTo": "true"}}}, "response": {"status": 200, "body": "{\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n },\n \"results\": [\n {\n \"hours\": 1619.7242069444444,\n \"total_hours\": 1621.7395791666668,\n \"agent_hours\": 41.33564388888889,\n \"tokens_in\": 0,\n \"tokens_out\": 0,\n \"tts_characters\": 9158866,\n \"requests\": 373381,\n \"grouping\": {\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-16\",\n \"accessor\": \"123456789012345678901234\",\n \"endpoint\": \"listen\",\n \"feature_set\": \"punctuate\",\n \"models\": [\n \"Nova-2\"\n ],\n \"method\": \"async\",\n \"tags\": \"tag1\",\n \"deployment\": \"self-hosted\"\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "9bdf51a4-1e10-41b8-8de2-2df650562db3", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "bc9fcd54-076e-48dc-a2dd-d71a8bf8bd4e", "name": "List Project Usage Fields - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/usage/fields", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"start": {"equalTo": "start"}, "end": {"equalTo": "end"}}}, "response": {"status": 200, "body": "{\n \"tags\": [\n \"tag=dev\",\n \"tag=production\"\n ],\n \"models\": [\n {\n \"name\": \"2-medical-nova\",\n \"language\": \"en-MY\",\n \"version\": \"2024-05-31.13574\",\n \"model_id\": \"1234567890-12345-67890\"\n }\n ],\n \"processing_methods\": [\n \"sync\",\n \"streaming\"\n ],\n \"features\": [\n \"alternatives\",\n \"detect_entities\",\n \"detect_language\"\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "bc9fcd54-076e-48dc-a2dd-d71a8bf8bd4e", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "b5ac3651-d3b7-4cd7-b0b8-e1a917a16f3b", "name": "Analyze text content - default", "request": {"urlPathTemplate": "/v1/read", "method": "POST", "queryParameters": {"callback": {"equalTo": "callback"}, "callback_method": {"equalTo": "POST"}, "sentiment": {"equalTo": "true"}, "summarize": {"equalTo": "v2"}, "tag": {"equalTo": "tag"}, "topics": {"equalTo": "true"}, "custom_topic": {"equalTo": "custom_topic"}, "custom_topic_mode": {"equalTo": "extended"}, "intents": {"equalTo": "true"}, "custom_intent": {"equalTo": "custom_intent"}, "custom_intent_mode": {"equalTo": "extended"}, "language": {"equalTo": "language"}}}, "response": {"status": 200, "body": "{\n \"metadata\": {\n \"metadata\": {\n \"request_id\": \"d04af392-db11-4c1d-83e1-20e34f0b8999\",\n \"created\": \"2024-11-18T23:47:44Z\",\n \"language\": \"en\"\n }\n },\n \"results\": {\n \"summary\": {\n \"results\": {\n \"summary\": {\n \"text\": \"The summary of the text submitted.\"\n }\n }\n },\n \"topics\": {\n \"results\": {\n \"topics\": {\n \"segments\": [\n {\n \"text\": \"And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 32,\n \"end_word\": 69,\n \"topics\": [\n {\n \"topic\": \"Spacewalk\",\n \"confidence_score\": 0.91581345\n }\n ]\n }\n ]\n }\n }\n },\n \"intents\": {\n \"results\": {\n \"intents\": {\n \"segments\": [\n {\n \"text\": \"If you found this valuable, you can subscribe to the show on spotify or your favorite podcast app.\",\n \"start_word\": 354,\n \"end_word\": 414,\n \"intents\": [\n {\n \"intent\": \"Encourage podcasting\",\n \"confidence_score\": 0.0038975573\n }\n ]\n }\n ]\n }\n }\n },\n \"sentiments\": {\n \"segments\": [\n {\n \"text\": \"Yeah. As as much as, um, it's worth celebrating, uh, the first, uh, spacewalk, um, with an all-female team, I think many of us are looking forward to it just being normal. And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 0,\n \"end_word\": 69,\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810546875\n }\n ],\n \"average\": {\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810185185185185\n }\n }\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "b5ac3651-d3b7-4cd7-b0b8-e1a917a16f3b", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "4110cb96-50e2-4fe6-b8ae-5d69120cee89", "name": "List Project Self-Hosted Distribution Credentials - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"distribution_credentials\": [\n {\n \"member\": {\n \"member_id\": \"3376abcd-8e5e-49d3-92d4-876d3a4f0363\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"8b36cfd0-472f-4a21-833f-2d6343c3a2f3\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "4110cb96-50e2-4fe6-b8ae-5d69120cee89", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "9c12eea9-6ba6-4d70-bb14-a2742cebc114", "name": "Create a Project Self-Hosted Distribution Credential - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials", "method": "POST", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}, "queryParameters": {"provider": {"equalTo": "quay"}}}, "response": {"status": 200, "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "9c12eea9-6ba6-4d70-bb14-a2742cebc114", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "a47cd13f-2314-4190-b2c7-20436ccffbd2", "name": "Get a Project Self-Hosted Distribution Credential - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials/{distribution_credentials_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "distribution_credentials_id": {"equalTo": "8b36cfd0-472f-4a21-833f-2d6343c3a2f3"}}}, "response": {"status": 200, "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "a47cd13f-2314-4190-b2c7-20436ccffbd2", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "8bd46091-0e57-4b3d-9485-a86e6f1eaf17", "name": "Delete a Project Self-Hosted Distribution Credential - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials/{distribution_credentials_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "distribution_credentials_id": {"equalTo": "8b36cfd0-472f-4a21-833f-2d6343c3a2f3"}}}, "response": {"status": 200, "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "8bd46091-0e57-4b3d-9485-a86e6f1eaf17", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "b06ec977-02ed-41e2-8fff-2bc45cd2166b", "name": "Text to Speech transformation - default", "request": {"urlPathTemplate": "/v1/speak", "method": "POST"}, "response": {"status": 200, "body": "{\n \"key\": \"value\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "b06ec977-02ed-41e2-8fff-2bc45cd2166b", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "61883f62-09ec-4be9-b477-13a89b9677cf", "name": "List Agent Configurations - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agents", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"agents\": [\n {\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "61883f62-09ec-4be9-b477-13a89b9677cf", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "a43cdbee-2b2f-47fb-8220-75d337cb6d3a", "name": "Create an Agent Configuration - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agents", "method": "POST", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n }\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "a43cdbee-2b2f-47fb-8220-75d337cb6d3a", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "2575dd3c-b1c8-4007-8f87-4e32073a9dcf", "name": "Get an Agent Configuration - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "agent_id": {"equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}}}, "response": {"status": 200, "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "2575dd3c-b1c8-4007-8f87-4e32073a9dcf", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "3b52c271-0e44-4148-b726-6f5ca8c91d26", "name": "Update Agent Metadata - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", "method": "PUT", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "agent_id": {"equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}}}, "response": {"status": 200, "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "3b52c271-0e44-4148-b726-6f5ca8c91d26", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "e839386d-beaa-4a7a-a478-ed9d9ab1b63e", "name": "Delete an Agent Configuration - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "agent_id": {"equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}}}, "response": {"status": 200, "body": "{\n \"key\": \"value\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "e839386d-beaa-4a7a-a478-ed9d9ab1b63e", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "bb85071e-3933-4cd3-8fd7-d35eb4c992c5", "name": "List Agent Variables - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agent-variables", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}}}, "response": {"status": 200, "body": "{\n \"variables\": [\n {\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n }\n ]\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "bb85071e-3933-4cd3-8fd7-d35eb4c992c5", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "c5016e4b-f863-4dc7-972f-c577ac7fdc47", "name": "Create an Agent Variable - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agent-variables", "method": "POST", "pathParameters": {"project_id": {"equalTo": "project_id"}}}, "response": {"status": 200, "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "c5016e4b-f863-4dc7-972f-c577ac7fdc47", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "5bb4b688-8475-4911-8ad5-725b7d5338e3", "name": "Get an Agent Variable - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", "method": "GET", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "variable_id": {"equalTo": "v1a2b3c4-d5e6-7890-abcd-ef1234567890"}}}, "response": {"status": 200, "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "5bb4b688-8475-4911-8ad5-725b7d5338e3", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "2e2c7061-7573-423f-a907-2a15dd9f3307", "name": "Delete an Agent Variable - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", "method": "DELETE", "pathParameters": {"project_id": {"equalTo": "123456-7890-1234-5678-901234"}, "variable_id": {"equalTo": "v1a2b3c4-d5e6-7890-abcd-ef1234567890"}}}, "response": {"status": 200, "body": "{\n \"key\": \"value\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "2e2c7061-7573-423f-a907-2a15dd9f3307", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}, {"id": "33765621-bc60-4ef4-b295-4b276aeb871f", "name": "Update an Agent Variable - default", "request": {"urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", "method": "PATCH", "pathParameters": {"project_id": {"equalTo": "project_id"}, "variable_id": {"equalTo": "variable_id"}}}, "response": {"status": 200, "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", "headers": {"Content-Type": "application/json"}}, "uuid": "33765621-bc60-4ef4-b295-4b276aeb871f", "persistent": true, "priority": 3, "metadata": {"mocklab": {"created": {"at": "2020-01-01T00:00:00.000Z", "via": "SYSTEM"}}}}], "meta": {"total": 49}} \ No newline at end of file +{ + "mappings": [ + { + "id": "533b5d52-ab21-4763-aaae-87cf52f49aa5", + "name": "List Agent Think Models - default", + "request": { + "urlPathTemplate": "/v1/agent/settings/think/models", + "method": "GET" + }, + "response": { + "status": 200, + "body": "{\n \"models\": [\n {\n \"id\": \"gpt-5\",\n \"name\": \"name\",\n \"provider\": \"open_ai\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "533b5d52-ab21-4763-aaae-87cf52f49aa5", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + }, + "postServeActions": [] + }, + { + "id": "20e1029e-8bb9-4092-a809-b943e60822ef", + "name": "Token-based Authentication - default", + "request": { + "urlPathTemplate": "/v1/auth/grant", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U\",\n \"expires_in\": 30\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "20e1029e-8bb9-4092-a809-b943e60822ef", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "49d8d51a-7f01-4598-804f-b6f54cdc22da", + "name": "Transcribe and analyze pre-recorded audio and video - default", + "request": { + "urlPathTemplate": "/v1/listen", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "queryParameters": { + "callback": { + "equalTo": "callback" + }, + "callback_method": { + "equalTo": "POST" + }, + "extra": { + "equalTo": "extra" + }, + "sentiment": { + "equalTo": "true" + }, + "summarize": { + "equalTo": "v2" + }, + "tag": { + "equalTo": "tag" + }, + "topics": { + "equalTo": "true" + }, + "custom_topic": { + "equalTo": "custom_topic" + }, + "custom_topic_mode": { + "equalTo": "extended" + }, + "intents": { + "equalTo": "true" + }, + "custom_intent": { + "equalTo": "custom_intent" + }, + "custom_intent_mode": { + "equalTo": "extended" + }, + "detect_entities": { + "equalTo": "true" + }, + "detect_language": { + "equalTo": "true" + }, + "diarize": { + "equalTo": "true" + }, + "dictation": { + "equalTo": "true" + }, + "encoding": { + "equalTo": "linear16" + }, + "filler_words": { + "equalTo": "true" + }, + "keyterm": { + "hasExactly": [ + { + "equalTo": "keyterm" + } + ] + }, + "keywords": { + "equalTo": "keywords" + }, + "language": { + "equalTo": "language" + }, + "measurements": { + "equalTo": "true" + }, + "model": { + "equalTo": "nova-3" + }, + "multichannel": { + "equalTo": "true" + }, + "numerals": { + "equalTo": "true" + }, + "paragraphs": { + "equalTo": "true" + }, + "profanity_filter": { + "equalTo": "true" + }, + "punctuate": { + "equalTo": "true" + }, + "redact": { + "equalTo": "redact" + }, + "replace": { + "equalTo": "replace" + }, + "search": { + "equalTo": "search" + }, + "smart_format": { + "equalTo": "true" + }, + "utterances": { + "equalTo": "true" + }, + "utt_split": { + "equalTo": "1.1" + }, + "version": { + "equalTo": "latest" + }, + "mip_opt_out": { + "equalTo": "true" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"metadata\": {\n \"request_id\": \"a847f427-4ad5-4d67-9b95-db801e58251c\",\n \"sha256\": \"154e291ecfa8be6ab8343560bcc109008fa7853eb5372533e8efdefc9b504c33\",\n \"created\": \"2024-05-12T18:57:13Z\",\n \"duration\": 25.933313,\n \"channels\": 1,\n \"models\": [\n \"30089e05-99d1-4376-b32e-c263170674af\"\n ],\n \"model_info\": {\n \"30089e05-99d1-4376-b32e-c263170674af\": {\n \"name\": \"2-general-nova\",\n \"version\": \"2024-01-09.29447\",\n \"arch\": \"nova-2\"\n }\n },\n \"summary_info\": {\n \"model_uuid\": \"67875a7f-c9c4-48a0-aa55-5bdb8a91c34a\",\n \"input_tokens\": 95,\n \"output_tokens\": 63\n },\n \"sentiment_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 105\n },\n \"topics_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 7\n },\n \"intents_info\": {\n \"model_uuid\": \"80ab3179-d113-4254-bd6b-4a2f96498695\",\n \"input_tokens\": 105,\n \"output_tokens\": 4\n },\n \"tags\": [\n \"test\"\n ]\n },\n \"results\": {\n \"channels\": [\n {}\n ],\n \"utterances\": [\n {}\n ],\n \"summary\": {\n \"result\": \"success\",\n \"short\": \"Speaker 0 discusses the significance of the first all-female spacewalk with an all-female team, stating that it is a tribute to the skilled and qualified women who were denied opportunities in the past.\"\n },\n \"topics\": {\n \"results\": {\n \"topics\": {\n \"segments\": [\n {\n \"text\": \"And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 32,\n \"end_word\": 69,\n \"topics\": [\n {\n \"topic\": \"Spacewalk\",\n \"confidence_score\": 0.91581345\n }\n ]\n }\n ]\n }\n }\n },\n \"intents\": {\n \"results\": {\n \"intents\": {\n \"segments\": [\n {\n \"text\": \"If you found this valuable, you can subscribe to the show on spotify or your favorite podcast app.\",\n \"start_word\": 354,\n \"end_word\": 414,\n \"intents\": [\n {\n \"intent\": \"Encourage podcasting\",\n \"confidence_score\": 0.0038975573\n }\n ]\n }\n ]\n }\n }\n },\n \"sentiments\": {\n \"segments\": [\n {\n \"text\": \"Yeah. As as much as, um, it's worth celebrating, uh, the first, uh, spacewalk, um, with an all-female team, I think many of us are looking forward to it just being normal. And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 0,\n \"end_word\": 69,\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810546875\n }\n ],\n \"average\": {\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810185185185185\n }\n }\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "49d8d51a-7f01-4598-804f-b6f54cdc22da", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "0a0be61b-f024-4120-9c54-23bca3e07c93", + "name": "List Models - default", + "request": { + "urlPathTemplate": "/v1/models", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "queryParameters": { + "include_outdated": { + "equalTo": "true" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"stt\": [\n {\n \"name\": \"nova-3\",\n \"canonical_name\": \"nova-3\",\n \"architecture\": \"base\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2021-11-10.1\",\n \"uuid\": \"6b28e919-8427-4f32-9847-492e2efd7daf\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": true\n }\n ],\n \"tts\": [\n {\n \"name\": \"zeus\",\n \"canonical_name\": \"aura-2-zeus-en\",\n \"architecture\": \"aura-2\",\n \"languages\": [\n \"en\",\n \"en-US\"\n ],\n \"version\": \"2025-04-07.0\",\n \"uuid\": \"2baf189d-91ac-481d-b6d1-750888667b31\",\n \"metadata\": {\n \"accent\": \"American\",\n \"age\": \"Adult\",\n \"color\": \"#C58DFF\",\n \"image\": \"https://static.deepgram.com/examples/avatars/zeus.jpg\",\n \"sample\": \"https://static.deepgram.com/examples/Aura-2-zeus.wav\",\n \"tags\": [\n \"masculine\",\n \"deep\",\n \"trustworthy\",\n \"smooth\"\n ],\n \"use_cases\": [\n \"IVR\"\n ]\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "0a0be61b-f024-4120-9c54-23bca3e07c93", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + }, + "postServeActions": [] + }, + { + "id": "0f94d3ea-43b6-4a1a-bce4-ab05b85440ae", + "name": "Get a specific Model - default", + "request": { + "urlPathTemplate": "/v1/models/{model_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "model_id": { + "equalTo": "af6e9977-99f6-4d8f-b6f5-dfdf6fb6e291" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"name\": \"general\",\n \"canonical_name\": \"enhanced-general\",\n \"architecture\": \"polaris\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2022-05-18.1\",\n \"uuid\": \"c7226e9e-ae1c-4057-ae2a-a71a6b0dc588\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": false\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "0f94d3ea-43b6-4a1a-bce4-ab05b85440ae", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "d08cac56-bc4d-4756-8fd1-d508914334d5", + "name": "List Projects - default", + "request": { + "urlPathTemplate": "/v1/projects", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"projects\": [\n {\n \"project_id\": \"project_id\",\n \"name\": \"name\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "d08cac56-bc4d-4756-8fd1-d508914334d5", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + }, + "postServeActions": [] + }, + { + "id": "6f0163a8-530c-4e25-bbe0-9ca86b9525dc", + "name": "Get a Project - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "limit": { + "equalTo": "1.1" + }, + "page": { + "equalTo": "1.1" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"project_id\": \"project_id\",\n \"mip_opt_out\": true,\n \"name\": \"name\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "6f0163a8-530c-4e25-bbe0-9ca86b9525dc", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "68918577-6401-4439-8533-356257ff7bcf", + "name": "Delete a Project - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "68918577-6401-4439-8533-356257ff7bcf", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "659fc38b-3934-4e43-93bf-d331f547449e", + "name": "Update a Project - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}", + "method": "PATCH", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"Successfully updated project info.\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "659fc38b-3934-4e43-93bf-d331f547449e", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "43ae6622-ad2f-4c81-9bc9-a8bbe17ef9d8", + "name": "Leave a Project - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/leave", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "43ae6622-ad2f-4c81-9bc9-a8bbe17ef9d8", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "032d9b1c-3b87-40fb-bfab-8c5be92a5d71", + "name": "List Project Keys - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/keys", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "status": { + "equalTo": "active" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"api_keys\": [\n {\n \"member\": {\n \"member_id\": \"1000-2000-3000-4000\",\n \"email\": \"john@test.com\"\n },\n \"api_key\": {\n \"api_key_id\": \"1234567890abcdef1234567890abcdef\",\n \"comment\": \"A comment\",\n \"scopes\": [\n \"admin\"\n ],\n \"created\": \"2021-01-01T00:00:00Z\"\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "032d9b1c-3b87-40fb-bfab-8c5be92a5d71", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "0167c735-0b6f-4715-8df8-32300d4dae72", + "name": "Create a Project Key - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/keys", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "project_id" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"api_key_id\": \"api_key_id\",\n \"key\": \"key\",\n \"comment\": \"comment\",\n \"scopes\": [\n \"scopes\",\n \"scopes\"\n ],\n \"tags\": [\n \"tags\",\n \"tags\"\n ],\n \"expiration_date\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "0167c735-0b6f-4715-8df8-32300d4dae72", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "c9812dd3-f87e-4798-aec3-af0933330dd5", + "name": "Get a Project Key - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/keys/{key_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "key_id": { + "equalTo": "123456789012345678901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"item\": {\n \"member\": {\n \"member_id\": \"1000-2000-3000-4000\",\n \"email\": \"john@test.com\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"api_key\": {\n \"api_key_id\": \"1000-2000-3000-4000\",\n \"comment\": \"A comment\",\n \"scopes\": [\n \"admin\"\n ],\n \"tags\": [\n \"prod\",\n \"west-region\"\n ],\n \"expiration_date\": \"2021-01-01T00:00:00Z\",\n \"created\": \"2021-01-01T00:00:00Z\"\n }\n }\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "c9812dd3-f87e-4798-aec3-af0933330dd5", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "3d2fbc7c-7bac-436f-a6ac-abe1b2c2caac", + "name": "Delete a Project Key - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/keys/{key_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "key_id": { + "equalTo": "123456789012345678901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "3d2fbc7c-7bac-436f-a6ac-abe1b2c2caac", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "91e103d5-72f7-463d-840d-310069e33de9", + "name": "List Project Members - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/members", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"members\": [\n {\n \"member_id\": \"member_id\",\n \"email\": \"email\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "91e103d5-72f7-463d-840d-310069e33de9", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "515c6f7e-09c3-43ea-ad6c-65bc11d20f46", + "name": "Delete a Project Member - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "member_id": { + "equalTo": "123456789012345678901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "515c6f7e-09c3-43ea-ad6c-65bc11d20f46", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "a920ad0e-2796-4361-ac16-ac83fb75e32a", + "name": "List Project Models - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/models", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "include_outdated": { + "equalTo": "true" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"stt\": [\n {\n \"name\": \"nova-3\",\n \"canonical_name\": \"nova-3\",\n \"architecture\": \"base\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2021-11-10.1\",\n \"uuid\": \"6b28e919-8427-4f32-9847-492e2efd7daf\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": true\n }\n ],\n \"tts\": [\n {\n \"name\": \"zeus\",\n \"canonical_name\": \"aura-2-zeus-en\",\n \"architecture\": \"aura-2\",\n \"languages\": [\n \"en\",\n \"en-US\"\n ],\n \"version\": \"2025-04-07.0\",\n \"uuid\": \"2baf189d-91ac-481d-b6d1-750888667b31\",\n \"metadata\": {\n \"accent\": \"American\",\n \"age\": \"Adult\",\n \"color\": \"#C58DFF\",\n \"image\": \"https://static.deepgram.com/examples/avatars/zeus.jpg\",\n \"sample\": \"https://static.deepgram.com/examples/Aura-2-zeus.wav\",\n \"tags\": [\n \"masculine\",\n \"deep\",\n \"trustworthy\",\n \"smooth\"\n ],\n \"use_cases\": [\n \"IVR\"\n ]\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "a920ad0e-2796-4361-ac16-ac83fb75e32a", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "9f8c6bf2-ebee-4956-b39f-0291b9d64b6e", + "name": "Get a Project Model - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/models/{model_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "model_id": { + "equalTo": "af6e9977-99f6-4d8f-b6f5-dfdf6fb6e291" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"name\": \"general\",\n \"canonical_name\": \"enhanced-general\",\n \"architecture\": \"polaris\",\n \"languages\": [\n \"en\",\n \"en-us\"\n ],\n \"version\": \"2022-05-18.1\",\n \"uuid\": \"c7226e9e-ae1c-4057-ae2a-a71a6b0dc588\",\n \"batch\": true,\n \"streaming\": true,\n \"formatted_output\": false\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "9f8c6bf2-ebee-4956-b39f-0291b9d64b6e", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "d6a14959-05fa-4aec-9f0c-ba2a817c66e5", + "name": "List Project Requests - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/requests", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "2024-01-15T09:30:00Z" + }, + "end": { + "equalTo": "2024-01-15T09:30:00Z" + }, + "limit": { + "equalTo": "1.1" + }, + "page": { + "equalTo": "1.1" + }, + "accessor": { + "equalTo": "12345678-1234-1234-1234-123456789012" + }, + "request_id": { + "equalTo": "12345678-1234-1234-1234-123456789012" + }, + "deployment": { + "equalTo": "hosted" + }, + "endpoint": { + "equalTo": "listen" + }, + "method": { + "equalTo": "sync" + }, + "status": { + "equalTo": "succeeded" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"page\": 1.1,\n \"limit\": 1.1,\n \"requests\": [\n {\n \"request_id\": \"request_id\",\n \"project_uuid\": \"project_uuid\",\n \"created\": \"2024-01-15T09:30:00Z\",\n \"path\": \"path\",\n \"api_key_id\": \"api_key_id\",\n \"response\": {\n \"key\": \"value\"\n },\n \"code\": 1.1,\n \"deployment\": \"deployment\",\n \"callback\": \"callback\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "d6a14959-05fa-4aec-9f0c-ba2a817c66e5", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "733e39aa-d3ef-4ea7-8062-af080c6288c4", + "name": "Get a Project Request - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/requests/{request_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "request_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"request\": {\n \"request_id\": \"request_id\",\n \"project_uuid\": \"project_uuid\",\n \"created\": \"2024-01-15T09:30:00Z\",\n \"path\": \"path\",\n \"api_key_id\": \"api_key_id\",\n \"response\": {\n \"key\": \"value\"\n },\n \"code\": 1.1,\n \"deployment\": \"deployment\",\n \"callback\": \"callback\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "733e39aa-d3ef-4ea7-8062-af080c6288c4", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "6309dd55-c993-4ce1-b0b2-01a41c9f08d6", + "name": "Get Project Usage - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/usage", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "start" + }, + "end": { + "equalTo": "end" + }, + "accessor": { + "equalTo": "12345678-1234-1234-1234-123456789012" + }, + "alternatives": { + "equalTo": "true" + }, + "callback_method": { + "equalTo": "true" + }, + "callback": { + "equalTo": "true" + }, + "channels": { + "equalTo": "true" + }, + "custom_intent_mode": { + "equalTo": "true" + }, + "custom_intent": { + "equalTo": "true" + }, + "custom_topic_mode": { + "equalTo": "true" + }, + "custom_topic": { + "equalTo": "true" + }, + "deployment": { + "equalTo": "hosted" + }, + "detect_entities": { + "equalTo": "true" + }, + "detect_language": { + "equalTo": "true" + }, + "diarize": { + "equalTo": "true" + }, + "dictation": { + "equalTo": "true" + }, + "encoding": { + "equalTo": "true" + }, + "endpoint": { + "equalTo": "listen" + }, + "extra": { + "equalTo": "true" + }, + "filler_words": { + "equalTo": "true" + }, + "intents": { + "equalTo": "true" + }, + "keyterm": { + "equalTo": "true" + }, + "keywords": { + "equalTo": "true" + }, + "language": { + "equalTo": "true" + }, + "measurements": { + "equalTo": "true" + }, + "method": { + "equalTo": "sync" + }, + "model": { + "equalTo": "6f548761-c9c0-429a-9315-11a1d28499c8" + }, + "multichannel": { + "equalTo": "true" + }, + "numerals": { + "equalTo": "true" + }, + "paragraphs": { + "equalTo": "true" + }, + "profanity_filter": { + "equalTo": "true" + }, + "punctuate": { + "equalTo": "true" + }, + "redact": { + "equalTo": "true" + }, + "replace": { + "equalTo": "true" + }, + "sample_rate": { + "equalTo": "true" + }, + "search": { + "equalTo": "true" + }, + "sentiment": { + "equalTo": "true" + }, + "smart_format": { + "equalTo": "true" + }, + "summarize": { + "equalTo": "true" + }, + "tag": { + "equalTo": "tag1" + }, + "topics": { + "equalTo": "true" + }, + "utt_split": { + "equalTo": "true" + }, + "utterances": { + "equalTo": "true" + }, + "version": { + "equalTo": "true" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"start\": \"2024-10-16\",\n \"end\": \"2024-10-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "6309dd55-c993-4ce1-b0b2-01a41c9f08d6", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "b132121b-4efe-42ad-a268-8acac35c189b", + "name": "Get Project Balances - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/balances", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"balances\": [\n {\n \"balance_id\": \"balance_id\",\n \"amount\": 1.1,\n \"units\": \"units\",\n \"purchase_order_id\": \"purchase_order_id\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "b132121b-4efe-42ad-a268-8acac35c189b", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "4019c244-52d3-4d57-902c-af837631650a", + "name": "Get a Project Balance - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/balances/{balance_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "balance_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"balance_id\": \"balance_id\",\n \"amount\": 1.1,\n \"units\": \"units\",\n \"purchase_order_id\": \"purchase_order_id\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "4019c244-52d3-4d57-902c-af837631650a", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "555b6751-587f-400c-bf5e-400e108ad6b4", + "name": "Get Project Billing Breakdown - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/billing/breakdown", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "start" + }, + "end": { + "equalTo": "end" + }, + "accessor": { + "equalTo": "12345678-1234-1234-1234-123456789012" + }, + "deployment": { + "equalTo": "hosted" + }, + "tag": { + "equalTo": "tag1" + }, + "line_item": { + "equalTo": "streaming::nova-3" + }, + "grouping": { + "hasExactly": [ + { + "equalTo": "deployment" + }, + { + "equalTo": "line_item" + } + ] + } + } + }, + "response": { + "status": 200, + "body": "{\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n },\n \"results\": [\n {\n \"dollars\": 0.25,\n \"grouping\": {\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-16\",\n \"accessor\": \"123456789012345678901234\",\n \"deployment\": \"hosted\",\n \"line_item\": \"streaming::nova-3\",\n \"tags\": [\n \"tag1\",\n \"tag2\"\n ]\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "555b6751-587f-400c-bf5e-400e108ad6b4", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "a61ae38c-e41f-4726-a55c-88f2135897be", + "name": "List Project Billing Fields - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/billing/fields", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "start" + }, + "end": { + "equalTo": "end" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"accessors\": [\n \"12345678-1234-1234-1234-123456789012\",\n \"87654321-4321-4321-4321-210987654321\"\n ],\n \"deployments\": [\n \"hosted\",\n \"self-hosted\"\n ],\n \"tags\": [\n \"dev\",\n \"production\"\n ],\n \"line_items\": {\n \"streaming::nova-3\": \"Nova - 3 (Stream)\",\n \"sync::aura-2\": \"Aura -2 (Sync)\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "a61ae38c-e41f-4726-a55c-88f2135897be", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "85b4373c-ba39-41b1-84e8-ae1ee6b180ca", + "name": "List Project Purchases - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/purchases", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "limit": { + "equalTo": "1.1" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"orders\": [\n {\n \"order_id\": \"025e19ba-b6d9-4a04-9f99-4fe715aca5f1\",\n \"expiration\": \"2026-03-04T00:00:00Z\",\n \"created\": \"2023-02-21T21:13:40Z\",\n \"amount\": 150,\n \"units\": \"usd\",\n \"order_type\": \"promotional\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "85b4373c-ba39-41b1-84e8-ae1ee6b180ca", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "2dd14c67-ed4e-4d97-9636-0a712899deb8", + "name": "List Project Invites - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/invites", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"invites\": [\n {\n \"email\": \"email\",\n \"scope\": \"scope\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "2dd14c67-ed4e-4d97-9636-0a712899deb8", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "7c109496-adfe-4e85-b007-a6f799ee95cb", + "name": "Create a Project Invite - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/invites", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "7c109496-adfe-4e85-b007-a6f799ee95cb", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "d6d268d0-d91e-4a65-80e0-339621173db9", + "name": "Delete a Project Invite - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/invites/{email}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "email": { + "equalTo": "john.doe@example.com" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "d6d268d0-d91e-4a65-80e0-339621173db9", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "1b965d71-c930-4a0b-90f3-2289f80f3634", + "name": "List Project Member Scopes - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}/scopes", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "member_id": { + "equalTo": "123456789012345678901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"scopes\": [\n \"scopes\"\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "1b965d71-c930-4a0b-90f3-2289f80f3634", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "eb2f5de2-b887-47be-abd5-7cb702aca55d", + "name": "Update Project Member Scopes - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/members/{member_id}/scopes", + "method": "PUT", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "member_id": { + "equalTo": "123456789012345678901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"message\": \"message\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "eb2f5de2-b887-47be-abd5-7cb702aca55d", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "9bdf51a4-1e10-41b8-8de2-2df650562db3", + "name": "Get Project Usage Breakdown - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/usage/breakdown", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "start" + }, + "end": { + "equalTo": "end" + }, + "grouping": { + "equalTo": "accessor" + }, + "accessor": { + "equalTo": "12345678-1234-1234-1234-123456789012" + }, + "alternatives": { + "equalTo": "true" + }, + "callback_method": { + "equalTo": "true" + }, + "callback": { + "equalTo": "true" + }, + "channels": { + "equalTo": "true" + }, + "custom_intent_mode": { + "equalTo": "true" + }, + "custom_intent": { + "equalTo": "true" + }, + "custom_topic_mode": { + "equalTo": "true" + }, + "custom_topic": { + "equalTo": "true" + }, + "deployment": { + "equalTo": "hosted" + }, + "detect_entities": { + "equalTo": "true" + }, + "detect_language": { + "equalTo": "true" + }, + "diarize": { + "equalTo": "true" + }, + "dictation": { + "equalTo": "true" + }, + "encoding": { + "equalTo": "true" + }, + "endpoint": { + "equalTo": "listen" + }, + "extra": { + "equalTo": "true" + }, + "filler_words": { + "equalTo": "true" + }, + "intents": { + "equalTo": "true" + }, + "keyterm": { + "equalTo": "true" + }, + "keywords": { + "equalTo": "true" + }, + "language": { + "equalTo": "true" + }, + "measurements": { + "equalTo": "true" + }, + "method": { + "equalTo": "sync" + }, + "model": { + "equalTo": "6f548761-c9c0-429a-9315-11a1d28499c8" + }, + "multichannel": { + "equalTo": "true" + }, + "numerals": { + "equalTo": "true" + }, + "paragraphs": { + "equalTo": "true" + }, + "profanity_filter": { + "equalTo": "true" + }, + "punctuate": { + "equalTo": "true" + }, + "redact": { + "equalTo": "true" + }, + "replace": { + "equalTo": "true" + }, + "sample_rate": { + "equalTo": "true" + }, + "search": { + "equalTo": "true" + }, + "sentiment": { + "equalTo": "true" + }, + "smart_format": { + "equalTo": "true" + }, + "summarize": { + "equalTo": "true" + }, + "tag": { + "equalTo": "tag1" + }, + "topics": { + "equalTo": "true" + }, + "utt_split": { + "equalTo": "true" + }, + "utterances": { + "equalTo": "true" + }, + "version": { + "equalTo": "true" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-23\",\n \"resolution\": {\n \"units\": \"day\",\n \"amount\": 1\n },\n \"results\": [\n {\n \"hours\": 1619.7242069444444,\n \"total_hours\": 1621.7395791666668,\n \"agent_hours\": 41.33564388888889,\n \"tokens_in\": 0,\n \"tokens_out\": 0,\n \"tts_characters\": 9158866,\n \"requests\": 373381,\n \"grouping\": {\n \"start\": \"2025-01-16\",\n \"end\": \"2025-01-16\",\n \"accessor\": \"123456789012345678901234\",\n \"endpoint\": \"listen\",\n \"feature_set\": \"punctuate\",\n \"models\": [\n \"Nova-2\"\n ],\n \"method\": \"async\",\n \"tags\": \"tag1\",\n \"deployment\": \"self-hosted\"\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "9bdf51a4-1e10-41b8-8de2-2df650562db3", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "bc9fcd54-076e-48dc-a2dd-d71a8bf8bd4e", + "name": "List Project Usage Fields - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/usage/fields", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "start": { + "equalTo": "start" + }, + "end": { + "equalTo": "end" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"tags\": [\n \"tag=dev\",\n \"tag=production\"\n ],\n \"models\": [\n {\n \"name\": \"2-medical-nova\",\n \"language\": \"en-MY\",\n \"version\": \"2024-05-31.13574\",\n \"model_id\": \"1234567890-12345-67890\"\n }\n ],\n \"processing_methods\": [\n \"sync\",\n \"streaming\"\n ],\n \"features\": [\n \"alternatives\",\n \"detect_entities\",\n \"detect_language\"\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "bc9fcd54-076e-48dc-a2dd-d71a8bf8bd4e", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "b5ac3651-d3b7-4cd7-b0b8-e1a917a16f3b", + "name": "Analyze text content - default", + "request": { + "urlPathTemplate": "/v1/read", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "queryParameters": { + "callback": { + "equalTo": "callback" + }, + "callback_method": { + "equalTo": "POST" + }, + "sentiment": { + "equalTo": "true" + }, + "summarize": { + "equalTo": "v2" + }, + "tag": { + "equalTo": "tag" + }, + "topics": { + "equalTo": "true" + }, + "custom_topic": { + "equalTo": "custom_topic" + }, + "custom_topic_mode": { + "equalTo": "extended" + }, + "intents": { + "equalTo": "true" + }, + "custom_intent": { + "equalTo": "custom_intent" + }, + "custom_intent_mode": { + "equalTo": "extended" + }, + "language": { + "equalTo": "language" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"metadata\": {\n \"metadata\": {\n \"request_id\": \"d04af392-db11-4c1d-83e1-20e34f0b8999\",\n \"created\": \"2024-11-18T23:47:44Z\",\n \"language\": \"en\"\n }\n },\n \"results\": {\n \"summary\": {\n \"results\": {\n \"summary\": {\n \"text\": \"The summary of the text submitted.\"\n }\n }\n },\n \"topics\": {\n \"results\": {\n \"topics\": {\n \"segments\": [\n {\n \"text\": \"And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 32,\n \"end_word\": 69,\n \"topics\": [\n {\n \"topic\": \"Spacewalk\",\n \"confidence_score\": 0.91581345\n }\n ]\n }\n ]\n }\n }\n },\n \"intents\": {\n \"results\": {\n \"intents\": {\n \"segments\": [\n {\n \"text\": \"If you found this valuable, you can subscribe to the show on spotify or your favorite podcast app.\",\n \"start_word\": 354,\n \"end_word\": 414,\n \"intents\": [\n {\n \"intent\": \"Encourage podcasting\",\n \"confidence_score\": 0.0038975573\n }\n ]\n }\n ]\n }\n }\n },\n \"sentiments\": {\n \"segments\": [\n {\n \"text\": \"Yeah. As as much as, um, it's worth celebrating, uh, the first, uh, spacewalk, um, with an all-female team, I think many of us are looking forward to it just being normal. And, um, I think if it signifies anything, it is, uh, to honor the the women who came before us who, um, were skilled and qualified, um, and didn't get the the same opportunities that we have today.\",\n \"start_word\": 0,\n \"end_word\": 69,\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810546875\n }\n ],\n \"average\": {\n \"sentiment\": \"positive\",\n \"sentiment_score\": 0.5810185185185185\n }\n }\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "b5ac3651-d3b7-4cd7-b0b8-e1a917a16f3b", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "4110cb96-50e2-4fe6-b8ae-5d69120cee89", + "name": "List Project Self-Hosted Distribution Credentials - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"distribution_credentials\": [\n {\n \"member\": {\n \"member_id\": \"3376abcd-8e5e-49d3-92d4-876d3a4f0363\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"8b36cfd0-472f-4a21-833f-2d6343c3a2f3\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "4110cb96-50e2-4fe6-b8ae-5d69120cee89", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "9c12eea9-6ba6-4d70-bb14-a2742cebc114", + "name": "Create a Project Self-Hosted Distribution Credential - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + }, + "queryParameters": { + "scopes": { + "hasExactly": [ + { + "equalTo": "self-hosted:products" + } + ] + }, + "provider": { + "equalTo": "quay" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "9c12eea9-6ba6-4d70-bb14-a2742cebc114", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "a47cd13f-2314-4190-b2c7-20436ccffbd2", + "name": "Get a Project Self-Hosted Distribution Credential - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials/{distribution_credentials_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "distribution_credentials_id": { + "equalTo": "8b36cfd0-472f-4a21-833f-2d6343c3a2f3" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "a47cd13f-2314-4190-b2c7-20436ccffbd2", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "8bd46091-0e57-4b3d-9485-a86e6f1eaf17", + "name": "Delete a Project Self-Hosted Distribution Credential - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/self-hosted/distribution/credentials/{distribution_credentials_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "distribution_credentials_id": { + "equalTo": "8b36cfd0-472f-4a21-833f-2d6343c3a2f3" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"member\": {\n \"member_id\": \"c7b9b131-73f3-11d9-8665-0b00d2e44b83\",\n \"email\": \"email@example.com\"\n },\n \"distribution_credentials\": {\n \"distribution_credentials_id\": \"82c32c10-53b2-4d23-993f-864b3d44502a\",\n \"provider\": \"quay\",\n \"comment\": \"My Self-Hosted Distribution Credentials\",\n \"scopes\": [\n \"self-hosted:product:api\",\n \"self-hosted:product:engine\"\n ],\n \"created\": \"2023-06-28T15:36:59Z\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "8bd46091-0e57-4b3d-9485-a86e6f1eaf17", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "b06ec977-02ed-41e2-8fff-2bc45cd2166b", + "name": "Text to Speech transformation - default", + "request": { + "urlPathTemplate": "/v1/speak", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"key\": \"value\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "b06ec977-02ed-41e2-8fff-2bc45cd2166b", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "61883f62-09ec-4be9-b477-13a89b9677cf", + "name": "List Agent Configurations - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agents", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"agents\": [\n {\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "61883f62-09ec-4be9-b477-13a89b9677cf", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "a43cdbee-2b2f-47fb-8220-75d337cb6d3a", + "name": "Create an Agent Configuration - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agents", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n }\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "a43cdbee-2b2f-47fb-8220-75d337cb6d3a", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "2575dd3c-b1c8-4007-8f87-4e32073a9dcf", + "name": "Get an Agent Configuration - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "agent_id": { + "equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "2575dd3c-b1c8-4007-8f87-4e32073a9dcf", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "3b52c271-0e44-4148-b726-6f5ca8c91d26", + "name": "Update Agent Metadata - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", + "method": "PUT", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "agent_id": { + "equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"agent_id\": \"agent_id\",\n \"config\": {\n \"key\": \"value\"\n },\n \"metadata\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "3b52c271-0e44-4148-b726-6f5ca8c91d26", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "e839386d-beaa-4a7a-a478-ed9d9ab1b63e", + "name": "Delete an Agent Configuration - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agents/{agent_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "agent_id": { + "equalTo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"key\": \"value\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "e839386d-beaa-4a7a-a478-ed9d9ab1b63e", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "bb85071e-3933-4cd3-8fd7-d35eb4c992c5", + "name": "List Agent Variables - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agent-variables", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"variables\": [\n {\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n }\n ]\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "bb85071e-3933-4cd3-8fd7-d35eb4c992c5", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "c5016e4b-f863-4dc7-972f-c577ac7fdc47", + "name": "Create an Agent Variable - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agent-variables", + "method": "POST", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "project_id" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "c5016e4b-f863-4dc7-972f-c577ac7fdc47", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "5bb4b688-8475-4911-8ad5-725b7d5338e3", + "name": "Get an Agent Variable - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", + "method": "GET", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "variable_id": { + "equalTo": "v1a2b3c4-d5e6-7890-abcd-ef1234567890" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "5bb4b688-8475-4911-8ad5-725b7d5338e3", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "2e2c7061-7573-423f-a907-2a15dd9f3307", + "name": "Delete an Agent Variable - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", + "method": "DELETE", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "123456-7890-1234-5678-901234" + }, + "variable_id": { + "equalTo": "v1a2b3c4-d5e6-7890-abcd-ef1234567890" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"key\": \"value\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "2e2c7061-7573-423f-a907-2a15dd9f3307", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + }, + { + "id": "33765621-bc60-4ef4-b295-4b276aeb871f", + "name": "Update an Agent Variable - default", + "request": { + "urlPathTemplate": "/v1/projects/{project_id}/agent-variables/{variable_id}", + "method": "PATCH", + "headers": { + "Authorization": { + "matches": ".+" + } + }, + "pathParameters": { + "project_id": { + "equalTo": "project_id" + }, + "variable_id": { + "equalTo": "variable_id" + } + } + }, + "response": { + "status": 200, + "body": "{\n \"variable_id\": \"variable_id\",\n \"key\": \"key\",\n \"value\": {\n \"key\": \"value\"\n },\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\"\n}", + "headers": { + "Content-Type": "application/json" + } + }, + "uuid": "33765621-bc60-4ef4-b295-4b276aeb871f", + "persistent": true, + "priority": 3, + "metadata": { + "mocklab": { + "created": { + "at": "2020-01-01T00:00:00.000Z", + "via": "SYSTEM" + } + } + } + } + ], + "meta": { + "total": 49 + } +} \ No newline at end of file From fe114ee10b8273b5cbb316731d4ef0f70837a2c0 Mon Sep 17 00:00:00 2001 From: Greg Holmes Date: Wed, 22 Apr 2026 11:27:47 +0100 Subject: [PATCH 4/5] chore: re-apply manual patches after regen --- .fernignore | 14 +- src/deepgram/agent/v1/socket_client.py | 38 +- src/deepgram/agent/v1/socket_client.py.bak | 357 ------------------ src/deepgram/listen/v1/socket_client.py | 30 +- src/deepgram/listen/v1/socket_client.py.bak | 234 ------------ src/deepgram/listen/v2/socket_client.py | 14 +- src/deepgram/listen/v2/socket_client.py.bak | 220 ----------- src/deepgram/speak/v1/socket_client.py | 30 +- src/deepgram/speak/v1/socket_client.py.bak | 235 ------------ ...ves_item_paragraphs_paragraphs_item.py.bak | 29 -- ..._v1response_results_utterances_item.py.bak | 28 -- ..._results_utterances_item_words_item.py.bak | 26 -- 12 files changed, 66 insertions(+), 1189 deletions(-) delete mode 100644 src/deepgram/agent/v1/socket_client.py.bak delete mode 100644 src/deepgram/listen/v1/socket_client.py.bak delete mode 100644 src/deepgram/listen/v2/socket_client.py.bak delete mode 100644 src/deepgram/speak/v1/socket_client.py.bak delete mode 100644 src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak delete mode 100644 src/deepgram/types/listen_v1response_results_utterances_item.py.bak delete mode 100644 src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak diff --git a/.fernignore b/.fernignore index 416c8831..0ded04e4 100644 --- a/.fernignore +++ b/.fernignore @@ -11,16 +11,10 @@ src/deepgram/client.py # - optional message param on control send_ methods (send_keep_alive, send_close_stream, etc.) # so users don't need to instantiate the type themselves for no-payload control messages # [temporarily frozen — generator bugs in construct_type call convention and exception handling] -src/deepgram/agent/v1/socket_client.py.bak -src/deepgram/listen/v1/socket_client.py.bak -src/deepgram/listen/v2/socket_client.py.bak -src/deepgram/speak/v1/socket_client.py.bak - -# Type files with manual int type corrections (Fern generates float for speaker/channel/num_words) -# [temporarily frozen — waiting on internal-api-specs#205] -src/deepgram/types/listen_v1response_results_utterances_item.py.bak -src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak -src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak +src/deepgram/agent/v1/socket_client.py +src/deepgram/listen/v1/socket_client.py +src/deepgram/listen/v2/socket_client.py +src/deepgram/speak/v1/socket_client.py # Hand-written custom tests tests/custom/test_text_builder.py diff --git a/src/deepgram/agent/v1/socket_client.py b/src/deepgram/agent/v1/socket_client.py index e89615cb..21b30ec1 100644 --- a/src/deepgram/agent/v1/socket_client.py +++ b/src/deepgram/agent/v1/socket_client.py @@ -3,9 +3,7 @@ import json import logging 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.unchecked_base_model import construct_type @@ -39,6 +37,26 @@ from websockets import WebSocketClientProtocol # type: ignore _logger = logging.getLogger(__name__) + + +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, @@ -102,7 +120,7 @@ async def start_listening(self): ) continue 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) @@ -142,12 +160,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(type="KeepAlive")) async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -196,7 +214,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): @@ -242,7 +260,7 @@ def start_listening(self): ) continue 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) @@ -282,12 +300,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(type="KeepAlive")) def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: """ @@ -336,4 +354,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/agent/v1/socket_client.py.bak b/src/deepgram/agent/v1/socket_client.py.bak deleted file mode 100644 index 21b30ec1..00000000 --- a/src/deepgram/agent/v1/socket_client.py.bak +++ /dev/null @@ -1,357 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import json -import logging -import typing - -import websockets.sync.connection as websockets_sync_connection -from ...core.events import EventEmitterMixin, EventType -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 -from .types.agent_v1conversation_text import AgentV1ConversationText -from .types.agent_v1error import AgentV1Error -from .types.agent_v1function_call_request import AgentV1FunctionCallRequest -from .types.agent_v1inject_agent_message import AgentV1InjectAgentMessage -from .types.agent_v1inject_user_message import AgentV1InjectUserMessage -from .types.agent_v1injection_refused import AgentV1InjectionRefused -from .types.agent_v1keep_alive import AgentV1KeepAlive -from .types.agent_v1prompt_updated import AgentV1PromptUpdated -from .types.agent_v1receive_function_call_response import AgentV1ReceiveFunctionCallResponse -from .types.agent_v1send_function_call_response import AgentV1SendFunctionCallResponse -from .types.agent_v1settings import AgentV1Settings -from .types.agent_v1settings_applied import AgentV1SettingsApplied -from .types.agent_v1speak_updated import AgentV1SpeakUpdated -from .types.agent_v1think_updated import AgentV1ThinkUpdated -from .types.agent_v1update_prompt import AgentV1UpdatePrompt -from .types.agent_v1update_speak import AgentV1UpdateSpeak -from .types.agent_v1update_think import AgentV1UpdateThink -from .types.agent_v1user_started_speaking import AgentV1UserStartedSpeaking -from .types.agent_v1warning import AgentV1Warning -from .types.agent_v1welcome import AgentV1Welcome - -try: - from websockets.legacy.client import WebSocketClientProtocol # type: ignore -except ImportError: - from websockets import WebSocketClientProtocol # type: ignore - -_logger = logging.getLogger(__name__) - - -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, - AgentV1SpeakUpdated, - AgentV1ThinkUpdated, - AgentV1InjectionRefused, - AgentV1Welcome, - AgentV1SettingsApplied, - AgentV1ConversationText, - AgentV1UserStartedSpeaking, - AgentV1AgentThinking, - AgentV1FunctionCallRequest, - AgentV1AgentStartedSpeaking, - AgentV1AgentAudioDone, - AgentV1Error, - AgentV1Warning, - bytes, -] - - -class AsyncV1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: WebSocketClientProtocol): - super().__init__() - self._websocket = websocket - - async def __aiter__(self): - async for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - async def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - await self._emit_async(EventType.OPEN, None) - try: - async for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: - await self._emit_async(EventType.ERROR, exc) - finally: - await self._emit_async(EventType.CLOSE, None) - - async def send_settings(self, message: AgentV1Settings) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1Settings. - """ - await self._send_model(message) - - async def send_update_speak(self, message: AgentV1UpdateSpeak) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdateSpeak. - """ - await self._send_model(message) - - async def send_inject_user_message(self, message: AgentV1InjectUserMessage) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1InjectUserMessage. - """ - await self._send_model(message) - - async def send_inject_agent_message(self, message: AgentV1InjectAgentMessage) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1InjectAgentMessage. - """ - await self._send_model(message) - - async def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1SendFunctionCallResponse. - """ - await self._send_model(message) - - 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 or AgentV1KeepAlive(type="KeepAlive")) - - async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdatePrompt. - """ - await self._send_model(message) - - async def send_update_think(self, message: AgentV1UpdateThink) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdateThink. - """ - await self._send_model(message) - - async def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - await self._send(message) - - async def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = await self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - async def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - await self._websocket.send(data) - - 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())) - - -class V1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: websockets_sync_connection.Connection): - super().__init__() - self._websocket = websocket - - def __iter__(self): - for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - self._emit(EventType.OPEN, None) - try: - for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - self._emit(EventType.MESSAGE, parsed) - except Exception as exc: - self._emit(EventType.ERROR, exc) - finally: - self._emit(EventType.CLOSE, None) - - def send_settings(self, message: AgentV1Settings) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1Settings. - """ - self._send_model(message) - - def send_update_speak(self, message: AgentV1UpdateSpeak) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdateSpeak. - """ - self._send_model(message) - - def send_inject_user_message(self, message: AgentV1InjectUserMessage) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1InjectUserMessage. - """ - self._send_model(message) - - def send_inject_agent_message(self, message: AgentV1InjectAgentMessage) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1InjectAgentMessage. - """ - self._send_model(message) - - def send_function_call_response(self, message: AgentV1SendFunctionCallResponse) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1SendFunctionCallResponse. - """ - self._send_model(message) - - 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 or AgentV1KeepAlive(type="KeepAlive")) - - def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdatePrompt. - """ - self._send_model(message) - - def send_update_think(self, message: AgentV1UpdateThink) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a AgentV1UpdateThink. - """ - self._send_model(message) - - def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - self._send(message) - - def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - self._websocket.send(data) - - def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - self._send(_sanitize_numeric_types(data.dict())) diff --git a/src/deepgram/listen/v1/socket_client.py b/src/deepgram/listen/v1/socket_client.py index cffa82b7..5954d116 100644 --- a/src/deepgram/listen/v1/socket_client.py +++ b/src/deepgram/listen/v1/socket_client.py @@ -3,9 +3,7 @@ import json import logging 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.unchecked_base_model import construct_type @@ -69,7 +67,7 @@ async def start_listening(self): ) continue 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) @@ -81,26 +79,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: """ @@ -174,7 +172,7 @@ def start_listening(self): ) continue 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) @@ -186,26 +184,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/v1/socket_client.py.bak b/src/deepgram/listen/v1/socket_client.py.bak deleted file mode 100644 index 5954d116..00000000 --- a/src/deepgram/listen/v1/socket_client.py.bak +++ /dev/null @@ -1,234 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import json -import logging -import typing - -import websockets.sync.connection as websockets_sync_connection -from ...core.events import EventEmitterMixin, EventType -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 -from .types.listen_v1metadata import ListenV1Metadata -from .types.listen_v1results import ListenV1Results -from .types.listen_v1speech_started import ListenV1SpeechStarted -from .types.listen_v1utterance_end import ListenV1UtteranceEnd - -try: - from websockets.legacy.client import WebSocketClientProtocol # type: ignore -except ImportError: - from websockets import WebSocketClientProtocol # type: ignore - -_logger = logging.getLogger(__name__) -V1SocketClientResponse = typing.Union[ListenV1Results, ListenV1Metadata, ListenV1UtteranceEnd, ListenV1SpeechStarted] - - -class AsyncV1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: WebSocketClientProtocol): - super().__init__() - self._websocket = websocket - - async def __aiter__(self): - async for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - async def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - await self._emit_async(EventType.OPEN, None) - try: - async for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: - await self._emit_async(EventType.ERROR, exc) - finally: - await self._emit_async(EventType.CLOSE, None) - - async def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - await self._send(message) - - 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 or ListenV1Finalize(type="Finalize")) - - 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 or ListenV1CloseStream(type="CloseStream")) - - 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 or ListenV1KeepAlive(type="KeepAlive")) - - async def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = await self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - async def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - await self._websocket.send(data) - - async def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - await self._send(data.dict()) - - -class V1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: websockets_sync_connection.Connection): - super().__init__() - self._websocket = websocket - - def __iter__(self): - for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - self._emit(EventType.OPEN, None) - try: - for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - self._emit(EventType.MESSAGE, parsed) - except Exception as exc: - self._emit(EventType.ERROR, exc) - finally: - self._emit(EventType.CLOSE, None) - - def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - self._send(message) - - 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 or ListenV1Finalize(type="Finalize")) - - 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 or ListenV1CloseStream(type="CloseStream")) - - 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 or ListenV1KeepAlive(type="KeepAlive")) - - def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - self._websocket.send(data) - - def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - self._send(data.dict()) diff --git a/src/deepgram/listen/v2/socket_client.py b/src/deepgram/listen/v2/socket_client.py index 696c5938..785fc22c 100644 --- a/src/deepgram/listen/v2/socket_client.py +++ b/src/deepgram/listen/v2/socket_client.py @@ -3,9 +3,7 @@ import json import logging 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.unchecked_base_model import construct_type @@ -71,7 +69,7 @@ async def start_listening(self): ) continue 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) @@ -83,12 +81,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 send_configure(self, message: ListenV2Configure) -> None: """ @@ -169,7 +167,7 @@ def start_listening(self): ) continue 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) @@ -181,12 +179,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 send_configure(self, message: ListenV2Configure) -> None: """ diff --git a/src/deepgram/listen/v2/socket_client.py.bak b/src/deepgram/listen/v2/socket_client.py.bak deleted file mode 100644 index d214f0f5..00000000 --- a/src/deepgram/listen/v2/socket_client.py.bak +++ /dev/null @@ -1,220 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import json -import logging -import typing - -import websockets.sync.connection as websockets_sync_connection -from ...core.events import EventEmitterMixin, EventType -from ...core.unchecked_base_model import construct_type -from .types.listen_v2close_stream import ListenV2CloseStream -from .types.listen_v2configure_failure import ListenV2ConfigureFailure -from .types.listen_v2connected import ListenV2Connected -from .types.listen_v2fatal_error import ListenV2FatalError -from .types.listen_v2turn_info import ListenV2TurnInfo - -try: - from websockets.legacy.client import WebSocketClientProtocol # type: ignore -except ImportError: - from websockets import WebSocketClientProtocol # type: ignore - -_logger = logging.getLogger(__name__) -V2SocketClientResponse = typing.Union[ - ListenV2Connected, ListenV2TurnInfo, typing.Any, ListenV2ConfigureFailure, ListenV2FatalError -] - - -class AsyncV2SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: WebSocketClientProtocol): - super().__init__() - self._websocket = websocket - - async def __aiter__(self): - async for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - async def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - await self._emit_async(EventType.OPEN, None) - try: - async for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: - await self._emit_async(EventType.ERROR, exc) - finally: - await self._emit_async(EventType.CLOSE, None) - - async def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - await self._send(message) - - 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 or ListenV2CloseStream(type="CloseStream")) - - async def send_configure(self, message: typing.Any) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a typing.Any. - """ - await self._send(message) - - async def recv(self) -> V2SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = await self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - async def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - await self._websocket.send(data) - - async def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - await self._send(data.dict()) - - -class V2SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: websockets_sync_connection.Connection): - super().__init__() - self._websocket = websocket - - def __iter__(self): - for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V2SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - self._emit(EventType.OPEN, None) - try: - for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - self._emit(EventType.MESSAGE, parsed) - except Exception as exc: - self._emit(EventType.ERROR, exc) - finally: - self._emit(EventType.CLOSE, None) - - def send_media(self, message: bytes) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a bytes. - """ - self._send(message) - - 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 or ListenV2CloseStream(type="CloseStream")) - - def send_configure(self, message: typing.Any) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a typing.Any. - """ - self._send(message) - - def recv(self) -> V2SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V2SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - self._websocket.send(data) - - def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - self._send(data.dict()) diff --git a/src/deepgram/speak/v1/socket_client.py b/src/deepgram/speak/v1/socket_client.py index 9f1cad28..e3c28bb5 100644 --- a/src/deepgram/speak/v1/socket_client.py +++ b/src/deepgram/speak/v1/socket_client.py @@ -3,9 +3,7 @@ import json import logging 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.unchecked_base_model import construct_type @@ -70,7 +68,7 @@ async def start_listening(self): ) continue 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) @@ -82,26 +80,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: """ @@ -175,7 +173,7 @@ def start_listening(self): ) continue 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) @@ -187,26 +185,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/speak/v1/socket_client.py.bak b/src/deepgram/speak/v1/socket_client.py.bak deleted file mode 100644 index e3c28bb5..00000000 --- a/src/deepgram/speak/v1/socket_client.py.bak +++ /dev/null @@ -1,235 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import json -import logging -import typing - -import websockets.sync.connection as websockets_sync_connection -from ...core.events import EventEmitterMixin, EventType -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 -from .types.speak_v1flush import SpeakV1Flush -from .types.speak_v1flushed import SpeakV1Flushed -from .types.speak_v1metadata import SpeakV1Metadata -from .types.speak_v1text import SpeakV1Text -from .types.speak_v1warning import SpeakV1Warning - -try: - from websockets.legacy.client import WebSocketClientProtocol # type: ignore -except ImportError: - from websockets import WebSocketClientProtocol # type: ignore - -_logger = logging.getLogger(__name__) -V1SocketClientResponse = typing.Union[bytes, SpeakV1Metadata, SpeakV1Flushed, SpeakV1Cleared, SpeakV1Warning] - - -class AsyncV1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: WebSocketClientProtocol): - super().__init__() - self._websocket = websocket - - async def __aiter__(self): - async for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - async def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - await self._emit_async(EventType.OPEN, None) - try: - async for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - await self._emit_async(EventType.MESSAGE, parsed) - except Exception as exc: - await self._emit_async(EventType.ERROR, exc) - finally: - await self._emit_async(EventType.CLOSE, None) - - async def send_text(self, message: SpeakV1Text) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a SpeakV1Text. - """ - await self._send_model(message) - - 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 or SpeakV1Flush(type="Flush")) - - 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 or SpeakV1Clear(type="Clear")) - - 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 or SpeakV1Close(type="Close")) - - async def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = await self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - async def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - await self._websocket.send(data) - - async def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - await self._send(data.dict()) - - -class V1SocketClient(EventEmitterMixin): - def __init__(self, *, websocket: websockets_sync_connection.Connection): - super().__init__() - self._websocket = websocket - - def __iter__(self): - for message in self._websocket: - if isinstance(message, bytes): - yield message - else: - try: - yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - - def start_listening(self): - """ - Start listening for messages on the websocket connection. - - Emits events in the following order: - - EventType.OPEN when connection is established - - EventType.MESSAGE for each message received - - EventType.ERROR if an error occurs - - EventType.CLOSE when connection is closed - """ - self._emit(EventType.OPEN, None) - try: - for raw_message in self._websocket: - if isinstance(raw_message, bytes): - parsed = raw_message - else: - json_data = json.loads(raw_message) - try: - parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning( - "Skipping unknown WebSocket message; update your SDK version to support new message types." - ) - continue - self._emit(EventType.MESSAGE, parsed) - except Exception as exc: - self._emit(EventType.ERROR, exc) - finally: - self._emit(EventType.CLOSE, None) - - def send_text(self, message: SpeakV1Text) -> None: - """ - Send a message to the websocket connection. - The message will be sent as a SpeakV1Text. - """ - self._send_model(message) - - 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 or SpeakV1Flush(type="Flush")) - - 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 or SpeakV1Clear(type="Clear")) - - 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 or SpeakV1Close(type="Close")) - - def recv(self) -> V1SocketClientResponse: - """ - Receive a message from the websocket connection. - """ - data = self._websocket.recv() - if isinstance(data, bytes): - return data # type: ignore - json_data = json.loads(data) - try: - return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore - except Exception: - _logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.") - return json_data # type: ignore - - def _send(self, data: typing.Any) -> None: - """ - Send a message to the websocket connection. - """ - if isinstance(data, dict): - data = json.dumps(data) - self._websocket.send(data) - - def _send_model(self, data: typing.Any) -> None: - """ - Send a Pydantic model to the websocket connection. - """ - self._send(data.dict()) diff --git a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak b/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak deleted file mode 100644 index eec3866b..00000000 --- a/src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak +++ /dev/null @@ -1,29 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -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(UncheckedBaseModel): - sentences: typing.Optional[ - typing.List[ListenV1ResponseResultsChannelsItemAlternativesItemParagraphsParagraphsItemSentencesItem] - ] = None - speaker: typing.Optional[int] = None - num_words: typing.Optional[int] = None - start: typing.Optional[float] = None - end: typing.Optional[float] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/deepgram/types/listen_v1response_results_utterances_item.py.bak b/src/deepgram/types/listen_v1response_results_utterances_item.py.bak deleted file mode 100644 index 0947d9f5..00000000 --- a/src/deepgram/types/listen_v1response_results_utterances_item.py.bak +++ /dev/null @@ -1,28 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -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(UncheckedBaseModel): - start: typing.Optional[float] = None - end: typing.Optional[float] = None - confidence: typing.Optional[float] = None - channel: typing.Optional[int] = None - transcript: typing.Optional[str] = None - words: typing.Optional[typing.List[ListenV1ResponseResultsUtterancesItemWordsItem]] = None - speaker: typing.Optional[int] = None - id: typing.Optional[str] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak b/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak deleted file mode 100644 index 6cd1313a..00000000 --- a/src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak +++ /dev/null @@ -1,26 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.unchecked_base_model import UncheckedBaseModel - - -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_confidence: typing.Optional[float] = None - punctuated_word: typing.Optional[str] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow From 87f8349ccbd86c82a69ad3ec918f4a58a2d03953 Mon Sep 17 00:00:00 2001 From: Greg Holmes Date: Wed, 22 Apr 2026 12:02:44 +0100 Subject: [PATCH 5/5] fix(ci): align workflows with generated Python 3.10+ support --- .github/workflows/ci.yml | 6 +++--- .github/workflows/release-please.yml | 6 +++--- .github/workflows/tests-daily.yml | 4 ++-- CONTRIBUTING.md | 2 +- README.md | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3df227cc..2128e6b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] needs: compile steps: - name: Checkout repo @@ -67,7 +67,7 @@ jobs: - name: Set up python uses: actions/setup-python@v6 with: - python-version: "3.8" + python-version: "3.10" - name: Bootstrap poetry run: | curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 45521a8b..764ba348 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -35,7 +35,7 @@ jobs: needs: compile strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -68,7 +68,7 @@ jobs: if: ${{ needs.release-please.outputs.release_created }} strategy: matrix: - python-version: ["3.8"] + python-version: ["3.10"] steps: - name: Checkout repo uses: actions/checkout@v4 diff --git a/.github/workflows/tests-daily.yml b/.github/workflows/tests-daily.yml index 2275aa12..6056869b 100644 --- a/.github/workflows/tests-daily.yml +++ b/.github/workflows/tests-daily.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] needs: compile steps: - name: Checkout repo diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a16a1b18..30db7821 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributions are welcome. This is a generated library, and changes to core files should be promoted to our generator code. -Requires Python 3.8+ +Requires Python 3.10+ ## Fork Repository diff --git a/README.md b/README.md index 5e325d51..92b9a090 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Built with Fern](https://img.shields.io/badge/%F0%9F%8C%BF-Built%20with%20Fern-brightgreen) [![PyPI version](https://img.shields.io/pypi/v/deepgram-sdk)](https://pypi.python.org/pypi/deepgram-sdk) -[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) The official Python SDK for Deepgram's automated speech recognition, text-to-speech, and language understanding APIs. Power your applications with world-class speech and Language AI models. @@ -464,7 +464,7 @@ See our [CONTRIBUTING](./CONTRIBUTING.md) guide. ### Requirements -- Python 3.8+ +- Python 3.10+ - See `pyproject.toml` for full dependency list ## Community Code of Conduct