Skip to content

Commit 855a30d

Browse files
SDK regeneration
1 parent 39ba701 commit 855a30d

File tree

15 files changed

+513
-86
lines changed

15 files changed

+513
-86
lines changed

.fern/metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"cliVersion": "4.4.1",
33
"generatorName": "fernapi/fern-python-sdk",
4-
"generatorVersion": "4.57.2",
4+
"generatorVersion": "4.61.4",
55
"generatorConfig": {
66
"client": {
77
"class_name": "BaseClient",

src/deepgram/agent/v1/socket_client.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# This file was auto-generated by Fern from our API Definition.
22

33
import json
4+
import logging
45
import typing
56
from json.decoder import JSONDecodeError
67

@@ -37,6 +38,7 @@
3738
except ImportError:
3839
from websockets import WebSocketClientProtocol # type: ignore
3940

41+
_logger = logging.getLogger(__name__)
4042
V1SocketClientResponse = typing.Union[
4143
AgentV1ReceiveFunctionCallResponse,
4244
AgentV1PromptUpdated,
@@ -67,7 +69,13 @@ async def __aiter__(self):
6769
if isinstance(message, bytes):
6870
yield message
6971
else:
70-
yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore
72+
try:
73+
yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore
74+
except Exception:
75+
_logger.warning(
76+
"Skipping unknown WebSocket message; update your SDK version to support new message types."
77+
)
78+
continue
7179

7280
async def start_listening(self):
7381
"""
@@ -86,7 +94,13 @@ async def start_listening(self):
8694
parsed = raw_message
8795
else:
8896
json_data = json.loads(raw_message)
89-
parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
97+
try:
98+
parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
99+
except Exception:
100+
_logger.warning(
101+
"Skipping unknown WebSocket message; update your SDK version to support new message types."
102+
)
103+
continue
90104
await self._emit_async(EventType.MESSAGE, parsed)
91105
except (websockets.WebSocketException, JSONDecodeError) as exc:
92106
await self._emit_async(EventType.ERROR, exc)
@@ -164,7 +178,11 @@ async def recv(self) -> V1SocketClientResponse:
164178
if isinstance(data, bytes):
165179
return data # type: ignore
166180
json_data = json.loads(data)
167-
return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
181+
try:
182+
return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
183+
except Exception:
184+
_logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.")
185+
return json_data # type: ignore
168186

169187
async def _send(self, data: typing.Any) -> None:
170188
"""
@@ -191,7 +209,13 @@ def __iter__(self):
191209
if isinstance(message, bytes):
192210
yield message
193211
else:
194-
yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore
212+
try:
213+
yield parse_obj_as(V1SocketClientResponse, json.loads(message)) # type: ignore
214+
except Exception:
215+
_logger.warning(
216+
"Skipping unknown WebSocket message; update your SDK version to support new message types."
217+
)
218+
continue
195219

196220
def start_listening(self):
197221
"""
@@ -210,7 +234,13 @@ def start_listening(self):
210234
parsed = raw_message
211235
else:
212236
json_data = json.loads(raw_message)
213-
parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
237+
try:
238+
parsed = parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
239+
except Exception:
240+
_logger.warning(
241+
"Skipping unknown WebSocket message; update your SDK version to support new message types."
242+
)
243+
continue
214244
self._emit(EventType.MESSAGE, parsed)
215245
except (websockets.WebSocketException, JSONDecodeError) as exc:
216246
self._emit(EventType.ERROR, exc)
@@ -288,7 +318,11 @@ def recv(self) -> V1SocketClientResponse:
288318
if isinstance(data, bytes):
289319
return data # type: ignore
290320
json_data = json.loads(data)
291-
return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
321+
try:
322+
return parse_obj_as(V1SocketClientResponse, json_data) # type: ignore
323+
except Exception:
324+
_logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.")
325+
return json_data # type: ignore
292326

293327
def _send(self, data: typing.Any) -> None:
294328
"""

src/deepgram/base_client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import httpx
99
from .core.api_error import ApiError
1010
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
11+
from .core.logging import LogConfig, Logger
1112
from .environment import DeepgramClientEnvironment
1213

1314
if typing.TYPE_CHECKING:
@@ -48,6 +49,9 @@ class BaseClient:
4849
httpx_client : typing.Optional[httpx.Client]
4950
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
5051
52+
logging : typing.Optional[typing.Union[LogConfig, Logger]]
53+
Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
54+
5155
Examples
5256
--------
5357
from deepgram import DeepgramClient
@@ -66,6 +70,7 @@ def __init__(
6670
timeout: typing.Optional[float] = None,
6771
follow_redirects: typing.Optional[bool] = True,
6872
httpx_client: typing.Optional[httpx.Client] = None,
73+
logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
6974
):
7075
_defaulted_timeout = (
7176
timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
@@ -84,6 +89,7 @@ def __init__(
8489
if follow_redirects is not None
8590
else httpx.Client(timeout=_defaulted_timeout),
8691
timeout=_defaulted_timeout,
92+
logging=logging,
8793
)
8894
self._agent: typing.Optional[AgentClient] = None
8995
self._auth: typing.Optional[AuthClient] = None
@@ -178,6 +184,9 @@ class AsyncBaseClient:
178184
httpx_client : typing.Optional[httpx.AsyncClient]
179185
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
180186
187+
logging : typing.Optional[typing.Union[LogConfig, Logger]]
188+
Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
189+
181190
Examples
182191
--------
183192
from deepgram import AsyncDeepgramClient
@@ -196,6 +205,7 @@ def __init__(
196205
timeout: typing.Optional[float] = None,
197206
follow_redirects: typing.Optional[bool] = True,
198207
httpx_client: typing.Optional[httpx.AsyncClient] = None,
208+
logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
199209
):
200210
_defaulted_timeout = (
201211
timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
@@ -214,6 +224,7 @@ def __init__(
214224
if follow_redirects is not None
215225
else httpx.AsyncClient(timeout=_defaulted_timeout),
216226
timeout=_defaulted_timeout,
227+
logging=logging,
217228
)
218229
self._agent: typing.Optional[AsyncAgentClient] = None
219230
self._auth: typing.Optional[AsyncAuthClient] = None

src/deepgram/core/__init__.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
if typing.TYPE_CHECKING:
99
from .api_error import ApiError
1010
from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
11-
from .datetime_utils import serialize_datetime
11+
from .datetime_utils import Rfc2822DateTime, parse_rfc2822_datetime, serialize_datetime
1212
from .events import EventEmitterMixin, EventType
1313
from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
1414
from .http_client import AsyncHttpClient, HttpClient
1515
from .http_response import AsyncHttpResponse, HttpResponse
1616
from .jsonable_encoder import jsonable_encoder
17+
from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger
1718
from .pydantic_utilities import (
1819
IS_PYDANTIC_V2,
1920
UniversalBaseModel,
@@ -35,15 +36,21 @@
3536
"AsyncHttpClient": ".http_client",
3637
"AsyncHttpResponse": ".http_response",
3738
"BaseClientWrapper": ".client_wrapper",
39+
"ConsoleLogger": ".logging",
3840
"EventEmitterMixin": ".events",
3941
"EventType": ".events",
4042
"FieldMetadata": ".serialization",
4143
"File": ".file",
4244
"HttpClient": ".http_client",
4345
"HttpResponse": ".http_response",
46+
"ILogger": ".logging",
4447
"IS_PYDANTIC_V2": ".pydantic_utilities",
4548
"InvalidWebSocketStatus": ".websocket_compat",
49+
"LogConfig": ".logging",
50+
"LogLevel": ".logging",
51+
"Logger": ".logging",
4652
"RequestOptions": ".request_options",
53+
"Rfc2822DateTime": ".datetime_utils",
4754
"SyncClientWrapper": ".client_wrapper",
4855
"UncheckedBaseModel": ".unchecked_base_model",
4956
"UnionMetadata": ".unchecked_base_model",
@@ -52,10 +59,12 @@
5259
"construct_type": ".unchecked_base_model",
5360
"convert_and_respect_annotation_metadata": ".serialization",
5461
"convert_file_dict_to_httpx_tuples": ".file",
62+
"create_logger": ".logging",
5563
"encode_query": ".query_encoder",
5664
"get_status_code": ".websocket_compat",
5765
"jsonable_encoder": ".jsonable_encoder",
5866
"parse_obj_as": ".pydantic_utilities",
67+
"parse_rfc2822_datetime": ".datetime_utils",
5968
"remove_none_from_dict": ".remove_none_from_dict",
6069
"serialize_datetime": ".datetime_utils",
6170
"universal_field_validator": ".pydantic_utilities",
@@ -92,15 +101,21 @@ def __dir__():
92101
"AsyncHttpClient",
93102
"AsyncHttpResponse",
94103
"BaseClientWrapper",
104+
"ConsoleLogger",
95105
"EventEmitterMixin",
96106
"EventType",
97107
"FieldMetadata",
98108
"File",
99109
"HttpClient",
100110
"HttpResponse",
111+
"ILogger",
101112
"IS_PYDANTIC_V2",
102113
"InvalidWebSocketStatus",
114+
"LogConfig",
115+
"LogLevel",
116+
"Logger",
103117
"RequestOptions",
118+
"Rfc2822DateTime",
104119
"SyncClientWrapper",
105120
"UncheckedBaseModel",
106121
"UnionMetadata",
@@ -109,10 +124,12 @@ def __dir__():
109124
"construct_type",
110125
"convert_and_respect_annotation_metadata",
111126
"convert_file_dict_to_httpx_tuples",
127+
"create_logger",
112128
"encode_query",
113129
"get_status_code",
114130
"jsonable_encoder",
115131
"parse_obj_as",
132+
"parse_rfc2822_datetime",
116133
"remove_none_from_dict",
117134
"serialize_datetime",
118135
"universal_field_validator",

src/deepgram/core/client_wrapper.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import httpx
66
from ..environment import DeepgramClientEnvironment
77
from .http_client import AsyncHttpClient, HttpClient
8+
from .logging import LogConfig, Logger
89

910

1011
class BaseClientWrapper:
@@ -15,11 +16,13 @@ def __init__(
1516
headers: typing.Optional[typing.Dict[str, str]] = None,
1617
environment: DeepgramClientEnvironment,
1718
timeout: typing.Optional[float] = None,
19+
logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
1820
):
1921
self.api_key = api_key
2022
self._headers = headers
2123
self._environment = environment
2224
self._timeout = timeout
25+
self._logging = logging
2326

2427
def get_headers(self) -> typing.Dict[str, str]:
2528
import platform
@@ -54,11 +57,15 @@ def __init__(
5457
headers: typing.Optional[typing.Dict[str, str]] = None,
5558
environment: DeepgramClientEnvironment,
5659
timeout: typing.Optional[float] = None,
60+
logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
5761
httpx_client: httpx.Client,
5862
):
59-
super().__init__(api_key=api_key, headers=headers, environment=environment, timeout=timeout)
63+
super().__init__(api_key=api_key, headers=headers, environment=environment, timeout=timeout, logging=logging)
6064
self.httpx_client = HttpClient(
61-
httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout
65+
httpx_client=httpx_client,
66+
base_headers=self.get_headers,
67+
base_timeout=self.get_timeout,
68+
logging_config=self._logging,
6269
)
6370

6471

@@ -70,16 +77,18 @@ def __init__(
7077
headers: typing.Optional[typing.Dict[str, str]] = None,
7178
environment: DeepgramClientEnvironment,
7279
timeout: typing.Optional[float] = None,
80+
logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
7381
async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
7482
httpx_client: httpx.AsyncClient,
7583
):
76-
super().__init__(api_key=api_key, headers=headers, environment=environment, timeout=timeout)
84+
super().__init__(api_key=api_key, headers=headers, environment=environment, timeout=timeout, logging=logging)
7785
self._async_token = async_token
7886
self.httpx_client = AsyncHttpClient(
7987
httpx_client=httpx_client,
8088
base_headers=self.get_headers,
8189
base_timeout=self.get_timeout,
8290
async_base_headers=self.async_get_headers,
91+
logging_config=self._logging,
8392
)
8493

8594
async def async_get_headers(self) -> typing.Dict[str, str]:

src/deepgram/core/datetime_utils.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
11
# This file was auto-generated by Fern from our API Definition.
22

33
import datetime as dt
4+
from email.utils import parsedate_to_datetime
5+
from typing import Any
6+
7+
import pydantic
8+
9+
IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
10+
11+
12+
def parse_rfc2822_datetime(v: Any) -> dt.datetime:
13+
"""
14+
Parse an RFC 2822 datetime string (e.g., "Wed, 02 Oct 2002 13:00:00 GMT")
15+
into a datetime object. If the value is already a datetime, return it as-is.
16+
Falls back to ISO 8601 parsing if RFC 2822 parsing fails.
17+
"""
18+
if isinstance(v, dt.datetime):
19+
return v
20+
if isinstance(v, str):
21+
try:
22+
return parsedate_to_datetime(v)
23+
except Exception:
24+
pass
25+
# Fallback to ISO 8601 parsing
26+
return dt.datetime.fromisoformat(v.replace("Z", "+00:00"))
27+
raise ValueError(f"Expected str or datetime, got {type(v)}")
28+
29+
30+
class Rfc2822DateTime(dt.datetime):
31+
"""A datetime subclass that parses RFC 2822 date strings.
32+
33+
On Pydantic V1, uses __get_validators__ for pre-validation.
34+
On Pydantic V2, uses __get_pydantic_core_schema__ for BeforeValidator-style parsing.
35+
"""
36+
37+
@classmethod
38+
def __get_validators__(cls): # type: ignore[no-untyped-def]
39+
yield parse_rfc2822_datetime
40+
41+
@classmethod
42+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: # type: ignore[override]
43+
from pydantic_core import core_schema
44+
45+
return core_schema.no_info_before_validator_function(parse_rfc2822_datetime, core_schema.datetime_schema())
446

547

648
def serialize_datetime(v: dt.datetime) -> str:

0 commit comments

Comments
 (0)