sarvamai 0.1.5a5__py3-none-any.whl → 0.1.5a6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sarvamai/__init__.py +1 -45
- sarvamai/chat/__init__.py +0 -2
- sarvamai/chat/client.py +10 -9
- sarvamai/chat/raw_client.py +37 -48
- sarvamai/client.py +31 -13
- sarvamai/core/__init__.py +0 -5
- sarvamai/core/api_error.py +5 -13
- sarvamai/core/client_wrapper.py +20 -17
- sarvamai/core/http_client.py +24 -70
- sarvamai/core/http_response.py +11 -19
- sarvamai/core/pydantic_utilities.py +108 -69
- sarvamai/environment.py +3 -10
- sarvamai/errors/__init__.py +0 -2
- sarvamai/errors/bad_request_error.py +3 -4
- sarvamai/errors/forbidden_error.py +3 -4
- sarvamai/errors/internal_server_error.py +3 -4
- sarvamai/errors/service_unavailable_error.py +2 -4
- sarvamai/errors/too_many_requests_error.py +3 -4
- sarvamai/errors/unprocessable_entity_error.py +3 -4
- sarvamai/requests/__init__.py +0 -18
- sarvamai/requests/chat_completion_request_message.py +1 -3
- sarvamai/requests/create_chat_completion_response.py +2 -2
- sarvamai/requests/diarized_transcript.py +1 -2
- sarvamai/requests/error_details.py +1 -0
- sarvamai/requests/language_identification_response.py +1 -0
- sarvamai/requests/speech_to_text_response.py +2 -1
- sarvamai/requests/speech_to_text_translate_response.py +1 -0
- sarvamai/requests/text_to_speech_response.py +2 -2
- sarvamai/requests/timestamps_model.py +1 -2
- sarvamai/requests/translation_response.py +1 -0
- sarvamai/requests/transliteration_response.py +1 -0
- sarvamai/speech_to_text/__init__.py +0 -2
- sarvamai/speech_to_text/client.py +14 -13
- sarvamai/speech_to_text/raw_client.py +68 -99
- sarvamai/text/__init__.py +0 -2
- sarvamai/text/client.py +25 -24
- sarvamai/text/raw_client.py +91 -126
- sarvamai/text_to_speech/__init__.py +0 -2
- sarvamai/text_to_speech/client.py +11 -10
- sarvamai/text_to_speech/raw_client.py +38 -49
- sarvamai/types/__init__.py +0 -24
- sarvamai/types/chat_completion_request_assistant_message.py +3 -3
- sarvamai/types/chat_completion_request_message.py +2 -3
- sarvamai/types/chat_completion_request_system_message.py +3 -3
- sarvamai/types/chat_completion_request_user_message.py +3 -3
- sarvamai/types/chat_completion_response_message.py +3 -3
- sarvamai/types/choice.py +4 -4
- sarvamai/types/completion_usage.py +3 -3
- sarvamai/types/create_chat_completion_response.py +3 -3
- sarvamai/types/diarized_entry.py +3 -3
- sarvamai/types/diarized_transcript.py +3 -3
- sarvamai/types/error_details.py +3 -3
- sarvamai/types/error_message.py +4 -4
- sarvamai/types/language_identification_response.py +2 -2
- sarvamai/types/speech_to_text_response.py +3 -3
- sarvamai/types/speech_to_text_translate_response.py +3 -3
- sarvamai/types/text_to_speech_response.py +2 -2
- sarvamai/types/timestamps_model.py +2 -2
- sarvamai/types/translation_response.py +2 -2
- sarvamai/types/transliteration_response.py +2 -2
- sarvamai-0.1.5a6.dist-info/METADATA +174 -0
- sarvamai-0.1.5a6.dist-info/RECORD +106 -0
- sarvamai/core/events.py +0 -30
- sarvamai/core/force_multipart.py +0 -16
- sarvamai/requests/audio_data.py +0 -21
- sarvamai/requests/audio_message.py +0 -8
- sarvamai/requests/error_data.py +0 -15
- sarvamai/requests/events_data.py +0 -17
- sarvamai/requests/speech_to_text_streaming_response.py +0 -10
- sarvamai/requests/speech_to_text_streaming_response_data.py +0 -9
- sarvamai/requests/transcription_data.py +0 -35
- sarvamai/requests/transcription_metrics.py +0 -15
- sarvamai/speech_to_text_streaming/__init__.py +0 -7
- sarvamai/speech_to_text_streaming/client.py +0 -189
- sarvamai/speech_to_text_streaming/raw_client.py +0 -166
- sarvamai/speech_to_text_streaming/socket_client.py +0 -129
- sarvamai/speech_to_text_streaming/types/__init__.py +0 -8
- sarvamai/speech_to_text_streaming/types/speech_to_text_streaming_language_code.py +0 -8
- sarvamai/speech_to_text_streaming/types/speech_to_text_streaming_model.py +0 -5
- sarvamai/types/audio_data.py +0 -33
- sarvamai/types/audio_data_encoding.py +0 -5
- sarvamai/types/audio_message.py +0 -20
- sarvamai/types/error_data.py +0 -27
- sarvamai/types/events_data.py +0 -28
- sarvamai/types/format.py +0 -5
- sarvamai/types/speech_to_text_streaming_response.py +0 -22
- sarvamai/types/speech_to_text_streaming_response_data.py +0 -9
- sarvamai/types/speech_to_text_streaming_response_type.py +0 -5
- sarvamai/types/transcription_data.py +0 -45
- sarvamai/types/transcription_metrics.py +0 -27
- sarvamai-0.1.5a5.dist-info/METADATA +0 -28
- sarvamai-0.1.5a5.dist-info/RECORD +0 -134
- {sarvamai-0.1.5a5.dist-info → sarvamai-0.1.5a6.dist-info}/WHEEL +0 -0
sarvamai/core/http_client.py
CHANGED
|
@@ -11,12 +11,10 @@ from random import random
|
|
|
11
11
|
|
|
12
12
|
import httpx
|
|
13
13
|
from .file import File, convert_file_dict_to_httpx_tuples
|
|
14
|
-
from .force_multipart import FORCE_MULTIPART
|
|
15
14
|
from .jsonable_encoder import jsonable_encoder
|
|
16
15
|
from .query_encoder import encode_query
|
|
17
16
|
from .remove_none_from_dict import remove_none_from_dict
|
|
18
17
|
from .request_options import RequestOptions
|
|
19
|
-
from httpx._types import RequestFiles
|
|
20
18
|
|
|
21
19
|
INITIAL_RETRY_DELAY_SECONDS = 0.5
|
|
22
20
|
MAX_RETRY_DELAY_SECONDS = 10
|
|
@@ -180,17 +178,11 @@ class HttpClient:
|
|
|
180
178
|
json: typing.Optional[typing.Any] = None,
|
|
181
179
|
data: typing.Optional[typing.Any] = None,
|
|
182
180
|
content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
|
|
183
|
-
files: typing.Optional[
|
|
184
|
-
typing.Union[
|
|
185
|
-
typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
|
|
186
|
-
typing.List[typing.Tuple[str, File]],
|
|
187
|
-
]
|
|
188
|
-
] = None,
|
|
181
|
+
files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
|
|
189
182
|
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
|
190
183
|
request_options: typing.Optional[RequestOptions] = None,
|
|
191
184
|
retries: int = 2,
|
|
192
185
|
omit: typing.Optional[typing.Any] = None,
|
|
193
|
-
force_multipart: typing.Optional[bool] = None,
|
|
194
186
|
) -> httpx.Response:
|
|
195
187
|
base_url = self.get_base_url(base_url)
|
|
196
188
|
timeout = (
|
|
@@ -201,15 +193,6 @@ class HttpClient:
|
|
|
201
193
|
|
|
202
194
|
json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
|
|
203
195
|
|
|
204
|
-
request_files: typing.Optional[RequestFiles] = (
|
|
205
|
-
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
206
|
-
if (files is not None and files is not omit and isinstance(files, dict))
|
|
207
|
-
else None
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
if (request_files is None or len(request_files) == 0) and force_multipart:
|
|
211
|
-
request_files = FORCE_MULTIPART
|
|
212
|
-
|
|
213
196
|
response = self.httpx_client.request(
|
|
214
197
|
method=method,
|
|
215
198
|
url=urllib.parse.urljoin(f"{base_url}/", path),
|
|
@@ -242,7 +225,11 @@ class HttpClient:
|
|
|
242
225
|
json=json_body,
|
|
243
226
|
data=data_body,
|
|
244
227
|
content=content,
|
|
245
|
-
files=
|
|
228
|
+
files=(
|
|
229
|
+
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
230
|
+
if (files is not None and files is not omit)
|
|
231
|
+
else None
|
|
232
|
+
),
|
|
246
233
|
timeout=timeout,
|
|
247
234
|
)
|
|
248
235
|
|
|
@@ -277,17 +264,11 @@ class HttpClient:
|
|
|
277
264
|
json: typing.Optional[typing.Any] = None,
|
|
278
265
|
data: typing.Optional[typing.Any] = None,
|
|
279
266
|
content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
|
|
280
|
-
files: typing.Optional[
|
|
281
|
-
typing.Union[
|
|
282
|
-
typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
|
|
283
|
-
typing.List[typing.Tuple[str, File]],
|
|
284
|
-
]
|
|
285
|
-
] = None,
|
|
267
|
+
files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
|
|
286
268
|
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
|
287
269
|
request_options: typing.Optional[RequestOptions] = None,
|
|
288
270
|
retries: int = 2,
|
|
289
271
|
omit: typing.Optional[typing.Any] = None,
|
|
290
|
-
force_multipart: typing.Optional[bool] = None,
|
|
291
272
|
) -> typing.Iterator[httpx.Response]:
|
|
292
273
|
base_url = self.get_base_url(base_url)
|
|
293
274
|
timeout = (
|
|
@@ -296,15 +277,6 @@ class HttpClient:
|
|
|
296
277
|
else self.base_timeout()
|
|
297
278
|
)
|
|
298
279
|
|
|
299
|
-
request_files: typing.Optional[RequestFiles] = (
|
|
300
|
-
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
301
|
-
if (files is not None and files is not omit and isinstance(files, dict))
|
|
302
|
-
else None
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
if (request_files is None or len(request_files) == 0) and force_multipart:
|
|
306
|
-
request_files = FORCE_MULTIPART
|
|
307
|
-
|
|
308
280
|
json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
|
|
309
281
|
|
|
310
282
|
with self.httpx_client.stream(
|
|
@@ -339,7 +311,11 @@ class HttpClient:
|
|
|
339
311
|
json=json_body,
|
|
340
312
|
data=data_body,
|
|
341
313
|
content=content,
|
|
342
|
-
files=
|
|
314
|
+
files=(
|
|
315
|
+
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
316
|
+
if (files is not None and files is not omit)
|
|
317
|
+
else None
|
|
318
|
+
),
|
|
343
319
|
timeout=timeout,
|
|
344
320
|
) as stream:
|
|
345
321
|
yield stream
|
|
@@ -378,17 +354,11 @@ class AsyncHttpClient:
|
|
|
378
354
|
json: typing.Optional[typing.Any] = None,
|
|
379
355
|
data: typing.Optional[typing.Any] = None,
|
|
380
356
|
content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
|
|
381
|
-
files: typing.Optional[
|
|
382
|
-
typing.Union[
|
|
383
|
-
typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
|
|
384
|
-
typing.List[typing.Tuple[str, File]],
|
|
385
|
-
]
|
|
386
|
-
] = None,
|
|
357
|
+
files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
|
|
387
358
|
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
|
388
359
|
request_options: typing.Optional[RequestOptions] = None,
|
|
389
360
|
retries: int = 2,
|
|
390
361
|
omit: typing.Optional[typing.Any] = None,
|
|
391
|
-
force_multipart: typing.Optional[bool] = None,
|
|
392
362
|
) -> httpx.Response:
|
|
393
363
|
base_url = self.get_base_url(base_url)
|
|
394
364
|
timeout = (
|
|
@@ -397,15 +367,6 @@ class AsyncHttpClient:
|
|
|
397
367
|
else self.base_timeout()
|
|
398
368
|
)
|
|
399
369
|
|
|
400
|
-
request_files: typing.Optional[RequestFiles] = (
|
|
401
|
-
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
402
|
-
if (files is not None and files is not omit and isinstance(files, dict))
|
|
403
|
-
else None
|
|
404
|
-
)
|
|
405
|
-
|
|
406
|
-
if (request_files is None or len(request_files) == 0) and force_multipart:
|
|
407
|
-
request_files = FORCE_MULTIPART
|
|
408
|
-
|
|
409
370
|
json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
|
|
410
371
|
|
|
411
372
|
# Add the input to each of these and do None-safety checks
|
|
@@ -441,7 +402,11 @@ class AsyncHttpClient:
|
|
|
441
402
|
json=json_body,
|
|
442
403
|
data=data_body,
|
|
443
404
|
content=content,
|
|
444
|
-
files=
|
|
405
|
+
files=(
|
|
406
|
+
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
407
|
+
if files is not None
|
|
408
|
+
else None
|
|
409
|
+
),
|
|
445
410
|
timeout=timeout,
|
|
446
411
|
)
|
|
447
412
|
|
|
@@ -475,17 +440,11 @@ class AsyncHttpClient:
|
|
|
475
440
|
json: typing.Optional[typing.Any] = None,
|
|
476
441
|
data: typing.Optional[typing.Any] = None,
|
|
477
442
|
content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
|
|
478
|
-
files: typing.Optional[
|
|
479
|
-
typing.Union[
|
|
480
|
-
typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
|
|
481
|
-
typing.List[typing.Tuple[str, File]],
|
|
482
|
-
]
|
|
483
|
-
] = None,
|
|
443
|
+
files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
|
|
484
444
|
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
|
485
445
|
request_options: typing.Optional[RequestOptions] = None,
|
|
486
446
|
retries: int = 2,
|
|
487
447
|
omit: typing.Optional[typing.Any] = None,
|
|
488
|
-
force_multipart: typing.Optional[bool] = None,
|
|
489
448
|
) -> typing.AsyncIterator[httpx.Response]:
|
|
490
449
|
base_url = self.get_base_url(base_url)
|
|
491
450
|
timeout = (
|
|
@@ -494,15 +453,6 @@ class AsyncHttpClient:
|
|
|
494
453
|
else self.base_timeout()
|
|
495
454
|
)
|
|
496
455
|
|
|
497
|
-
request_files: typing.Optional[RequestFiles] = (
|
|
498
|
-
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
499
|
-
if (files is not None and files is not omit and isinstance(files, dict))
|
|
500
|
-
else None
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
if (request_files is None or len(request_files) == 0) and force_multipart:
|
|
504
|
-
request_files = FORCE_MULTIPART
|
|
505
|
-
|
|
506
456
|
json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
|
|
507
457
|
|
|
508
458
|
async with self.httpx_client.stream(
|
|
@@ -537,7 +487,11 @@ class AsyncHttpClient:
|
|
|
537
487
|
json=json_body,
|
|
538
488
|
data=data_body,
|
|
539
489
|
content=content,
|
|
540
|
-
files=
|
|
490
|
+
files=(
|
|
491
|
+
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
|
|
492
|
+
if files is not None
|
|
493
|
+
else None
|
|
494
|
+
),
|
|
541
495
|
timeout=timeout,
|
|
542
496
|
) as stream:
|
|
543
497
|
yield stream
|
sarvamai/core/http_response.py
CHANGED
|
@@ -5,31 +5,20 @@ from typing import Dict, Generic, TypeVar
|
|
|
5
5
|
import httpx
|
|
6
6
|
|
|
7
7
|
T = TypeVar("T")
|
|
8
|
-
"""Generic to represent the underlying type of the data wrapped by the HTTP response."""
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
class
|
|
12
|
-
"""Minimalist HTTP response wrapper that exposes response headers."""
|
|
13
|
-
|
|
10
|
+
class HttpResponse(Generic[T]):
|
|
14
11
|
_response: httpx.Response
|
|
12
|
+
_data: T
|
|
15
13
|
|
|
16
|
-
def __init__(self, response: httpx.Response):
|
|
14
|
+
def __init__(self, response: httpx.Response, data: T):
|
|
17
15
|
self._response = response
|
|
16
|
+
self._data = data
|
|
18
17
|
|
|
19
18
|
@property
|
|
20
19
|
def headers(self) -> Dict[str, str]:
|
|
21
20
|
return dict(self._response.headers)
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
class HttpResponse(Generic[T], BaseHttpResponse):
|
|
25
|
-
"""HTTP response wrapper that exposes response headers and data."""
|
|
26
|
-
|
|
27
|
-
_data: T
|
|
28
|
-
|
|
29
|
-
def __init__(self, response: httpx.Response, data: T):
|
|
30
|
-
super().__init__(response)
|
|
31
|
-
self._data = data
|
|
32
|
-
|
|
33
22
|
@property
|
|
34
23
|
def data(self) -> T:
|
|
35
24
|
return self._data
|
|
@@ -38,15 +27,18 @@ class HttpResponse(Generic[T], BaseHttpResponse):
|
|
|
38
27
|
self._response.close()
|
|
39
28
|
|
|
40
29
|
|
|
41
|
-
class AsyncHttpResponse(Generic[T]
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
class AsyncHttpResponse(Generic[T]):
|
|
31
|
+
_response: httpx.Response
|
|
44
32
|
_data: T
|
|
45
33
|
|
|
46
34
|
def __init__(self, response: httpx.Response, data: T):
|
|
47
|
-
|
|
35
|
+
self._response = response
|
|
48
36
|
self._data = data
|
|
49
37
|
|
|
38
|
+
@property
|
|
39
|
+
def headers(self) -> Dict[str, str]:
|
|
40
|
+
return dict(self._response.headers)
|
|
41
|
+
|
|
50
42
|
@property
|
|
51
43
|
def data(self) -> T:
|
|
52
44
|
return self._data
|
|
@@ -2,65 +2,87 @@
|
|
|
2
2
|
|
|
3
3
|
# nopycln: file
|
|
4
4
|
import datetime as dt
|
|
5
|
+
import typing
|
|
5
6
|
from collections import defaultdict
|
|
6
|
-
from typing import Any, Callable, ClassVar, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar, Union, cast
|
|
7
7
|
|
|
8
8
|
import pydantic
|
|
9
|
+
import typing_extensions
|
|
10
|
+
from .datetime_utils import serialize_datetime
|
|
11
|
+
from .serialization import convert_and_respect_annotation_metadata
|
|
9
12
|
|
|
10
13
|
IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
|
|
11
14
|
|
|
12
15
|
if IS_PYDANTIC_V2:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from pydantic.v1.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
from pydantic.v1.
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
# isort will try to reformat the comments on these imports, which breaks mypy
|
|
17
|
+
# isort: off
|
|
18
|
+
from pydantic.v1.datetime_parse import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
19
|
+
parse_date as parse_date,
|
|
20
|
+
)
|
|
21
|
+
from pydantic.v1.datetime_parse import ( # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
22
|
+
parse_datetime as parse_datetime,
|
|
23
|
+
)
|
|
24
|
+
from pydantic.v1.json import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
25
|
+
ENCODERS_BY_TYPE as encoders_by_type,
|
|
26
|
+
)
|
|
27
|
+
from pydantic.v1.typing import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
28
|
+
get_args as get_args,
|
|
29
|
+
)
|
|
30
|
+
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
31
|
+
get_origin as get_origin,
|
|
32
|
+
)
|
|
33
|
+
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
34
|
+
is_literal_type as is_literal_type,
|
|
35
|
+
)
|
|
36
|
+
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
37
|
+
is_union as is_union,
|
|
38
|
+
)
|
|
39
|
+
from pydantic.v1.fields import ModelField as ModelField # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
|
|
21
40
|
else:
|
|
22
|
-
from pydantic.datetime_parse import parse_date as parse_date # type: ignore
|
|
23
|
-
from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore
|
|
24
|
-
from pydantic.fields import ModelField as ModelField # type: ignore
|
|
25
|
-
from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore
|
|
26
|
-
from pydantic.typing import get_args as get_args # type: ignore
|
|
27
|
-
from pydantic.typing import get_origin as get_origin # type: ignore
|
|
28
|
-
from pydantic.typing import is_literal_type as is_literal_type # type: ignore
|
|
29
|
-
from pydantic.typing import is_union as is_union # type: ignore
|
|
41
|
+
from pydantic.datetime_parse import parse_date as parse_date # type: ignore # Pydantic v1
|
|
42
|
+
from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore # Pydantic v1
|
|
43
|
+
from pydantic.fields import ModelField as ModelField # type: ignore # Pydantic v1
|
|
44
|
+
from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore # Pydantic v1
|
|
45
|
+
from pydantic.typing import get_args as get_args # type: ignore # Pydantic v1
|
|
46
|
+
from pydantic.typing import get_origin as get_origin # type: ignore # Pydantic v1
|
|
47
|
+
from pydantic.typing import is_literal_type as is_literal_type # type: ignore # Pydantic v1
|
|
48
|
+
from pydantic.typing import is_union as is_union # type: ignore # Pydantic v1
|
|
49
|
+
|
|
50
|
+
# isort: on
|
|
30
51
|
|
|
31
|
-
from .datetime_utils import serialize_datetime
|
|
32
|
-
from .serialization import convert_and_respect_annotation_metadata
|
|
33
|
-
from typing_extensions import TypeAlias
|
|
34
52
|
|
|
35
|
-
T = TypeVar("T")
|
|
36
|
-
Model = TypeVar("Model", bound=pydantic.BaseModel)
|
|
53
|
+
T = typing.TypeVar("T")
|
|
54
|
+
Model = typing.TypeVar("Model", bound=pydantic.BaseModel)
|
|
37
55
|
|
|
38
56
|
|
|
39
|
-
def parse_obj_as(type_: Type[T], object_: Any) -> T:
|
|
57
|
+
def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T:
|
|
40
58
|
dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
|
|
41
59
|
if IS_PYDANTIC_V2:
|
|
42
|
-
adapter = pydantic.TypeAdapter(type_) # type: ignore
|
|
60
|
+
adapter = pydantic.TypeAdapter(type_) # type: ignore # Pydantic v2
|
|
43
61
|
return adapter.validate_python(dealiased_object)
|
|
44
|
-
|
|
62
|
+
else:
|
|
63
|
+
return pydantic.parse_obj_as(type_, dealiased_object)
|
|
45
64
|
|
|
46
65
|
|
|
47
|
-
def to_jsonable_with_fallback(
|
|
66
|
+
def to_jsonable_with_fallback(
|
|
67
|
+
obj: typing.Any, fallback_serializer: typing.Callable[[typing.Any], typing.Any]
|
|
68
|
+
) -> typing.Any:
|
|
48
69
|
if IS_PYDANTIC_V2:
|
|
49
70
|
from pydantic_core import to_jsonable_python
|
|
50
71
|
|
|
51
72
|
return to_jsonable_python(obj, fallback=fallback_serializer)
|
|
52
|
-
|
|
73
|
+
else:
|
|
74
|
+
return fallback_serializer(obj)
|
|
53
75
|
|
|
54
76
|
|
|
55
77
|
class UniversalBaseModel(pydantic.BaseModel):
|
|
56
78
|
if IS_PYDANTIC_V2:
|
|
57
|
-
model_config: ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
79
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
58
80
|
# Allow fields beginning with `model_` to be used in the model
|
|
59
81
|
protected_namespaces=(),
|
|
60
|
-
)
|
|
82
|
+
) # type: ignore # Pydantic v2
|
|
61
83
|
|
|
62
|
-
@pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore
|
|
63
|
-
def serialize_model(self, handler: pydantic.SerializerFunctionWrapHandler) -> Any: # type: ignore
|
|
84
|
+
@pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2
|
|
85
|
+
def serialize_model(self, handler: pydantic.SerializerFunctionWrapHandler) -> typing.Any: # type: ignore # Pydantic v2
|
|
64
86
|
serialized = handler(self)
|
|
65
87
|
data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()}
|
|
66
88
|
return data
|
|
@@ -72,28 +94,34 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
|
72
94
|
json_encoders = {dt.datetime: serialize_datetime}
|
|
73
95
|
|
|
74
96
|
@classmethod
|
|
75
|
-
def model_construct(
|
|
97
|
+
def model_construct(
|
|
98
|
+
cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any
|
|
99
|
+
) -> "Model":
|
|
76
100
|
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
|
|
77
101
|
return cls.construct(_fields_set, **dealiased_object)
|
|
78
102
|
|
|
79
103
|
@classmethod
|
|
80
|
-
def construct(
|
|
104
|
+
def construct(
|
|
105
|
+
cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any
|
|
106
|
+
) -> "Model":
|
|
81
107
|
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
|
|
82
108
|
if IS_PYDANTIC_V2:
|
|
83
|
-
return super().model_construct(_fields_set, **dealiased_object) # type: ignore
|
|
84
|
-
|
|
109
|
+
return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2
|
|
110
|
+
else:
|
|
111
|
+
return super().construct(_fields_set, **dealiased_object)
|
|
85
112
|
|
|
86
|
-
def json(self, **kwargs: Any) -> str:
|
|
87
|
-
kwargs_with_defaults = {
|
|
113
|
+
def json(self, **kwargs: typing.Any) -> str:
|
|
114
|
+
kwargs_with_defaults: typing.Any = {
|
|
88
115
|
"by_alias": True,
|
|
89
116
|
"exclude_unset": True,
|
|
90
117
|
**kwargs,
|
|
91
118
|
}
|
|
92
119
|
if IS_PYDANTIC_V2:
|
|
93
|
-
return super().model_dump_json(**kwargs_with_defaults) # type: ignore
|
|
94
|
-
|
|
120
|
+
return super().model_dump_json(**kwargs_with_defaults) # type: ignore # Pydantic v2
|
|
121
|
+
else:
|
|
122
|
+
return super().json(**kwargs_with_defaults)
|
|
95
123
|
|
|
96
|
-
def dict(self, **kwargs: Any) -> Dict[str, Any]:
|
|
124
|
+
def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
|
|
97
125
|
"""
|
|
98
126
|
Override the default dict method to `exclude_unset` by default. This function patches
|
|
99
127
|
`exclude_unset` to work include fields within non-None default values.
|
|
@@ -104,21 +132,21 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
|
104
132
|
# We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models
|
|
105
133
|
# that we have less control over, and this is less intrusive than custom serializers for now.
|
|
106
134
|
if IS_PYDANTIC_V2:
|
|
107
|
-
kwargs_with_defaults_exclude_unset = {
|
|
135
|
+
kwargs_with_defaults_exclude_unset: typing.Any = {
|
|
108
136
|
**kwargs,
|
|
109
137
|
"by_alias": True,
|
|
110
138
|
"exclude_unset": True,
|
|
111
139
|
"exclude_none": False,
|
|
112
140
|
}
|
|
113
|
-
kwargs_with_defaults_exclude_none = {
|
|
141
|
+
kwargs_with_defaults_exclude_none: typing.Any = {
|
|
114
142
|
**kwargs,
|
|
115
143
|
"by_alias": True,
|
|
116
144
|
"exclude_none": True,
|
|
117
145
|
"exclude_unset": False,
|
|
118
146
|
}
|
|
119
147
|
dict_dump = deep_union_pydantic_dicts(
|
|
120
|
-
super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore
|
|
121
|
-
super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore
|
|
148
|
+
super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2
|
|
149
|
+
super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2
|
|
122
150
|
)
|
|
123
151
|
|
|
124
152
|
else:
|
|
@@ -138,7 +166,7 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
|
138
166
|
if default is not None:
|
|
139
167
|
self.__fields_set__.add(name)
|
|
140
168
|
|
|
141
|
-
kwargs_with_defaults_exclude_unset_include_fields = {
|
|
169
|
+
kwargs_with_defaults_exclude_unset_include_fields: typing.Any = {
|
|
142
170
|
"by_alias": True,
|
|
143
171
|
"exclude_unset": True,
|
|
144
172
|
"include": _fields_set,
|
|
@@ -150,10 +178,12 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
|
150
178
|
return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
|
|
151
179
|
|
|
152
180
|
|
|
153
|
-
def _union_list_of_pydantic_dicts(
|
|
154
|
-
|
|
181
|
+
def _union_list_of_pydantic_dicts(
|
|
182
|
+
source: typing.List[typing.Any], destination: typing.List[typing.Any]
|
|
183
|
+
) -> typing.List[typing.Any]:
|
|
184
|
+
converted_list: typing.List[typing.Any] = []
|
|
155
185
|
for i, item in enumerate(source):
|
|
156
|
-
destination_value = destination[i]
|
|
186
|
+
destination_value = destination[i] # type: ignore
|
|
157
187
|
if isinstance(item, dict):
|
|
158
188
|
converted_list.append(deep_union_pydantic_dicts(item, destination_value))
|
|
159
189
|
elif isinstance(item, list):
|
|
@@ -163,7 +193,9 @@ def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) ->
|
|
|
163
193
|
return converted_list
|
|
164
194
|
|
|
165
195
|
|
|
166
|
-
def deep_union_pydantic_dicts(
|
|
196
|
+
def deep_union_pydantic_dicts(
|
|
197
|
+
source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any]
|
|
198
|
+
) -> typing.Dict[str, typing.Any]:
|
|
167
199
|
for key, value in source.items():
|
|
168
200
|
node = destination.setdefault(key, {})
|
|
169
201
|
if isinstance(value, dict):
|
|
@@ -181,16 +213,18 @@ def deep_union_pydantic_dicts(source: Dict[str, Any], destination: Dict[str, Any
|
|
|
181
213
|
|
|
182
214
|
if IS_PYDANTIC_V2:
|
|
183
215
|
|
|
184
|
-
class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore
|
|
216
|
+
class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore # Pydantic v2
|
|
185
217
|
pass
|
|
186
218
|
|
|
187
|
-
UniversalRootModel: TypeAlias = V2RootModel # type: ignore
|
|
219
|
+
UniversalRootModel: typing_extensions.TypeAlias = V2RootModel # type: ignore
|
|
188
220
|
else:
|
|
189
|
-
UniversalRootModel: TypeAlias = UniversalBaseModel # type: ignore
|
|
221
|
+
UniversalRootModel: typing_extensions.TypeAlias = UniversalBaseModel # type: ignore
|
|
190
222
|
|
|
191
223
|
|
|
192
|
-
def encode_by_type(o: Any) -> Any:
|
|
193
|
-
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] =
|
|
224
|
+
def encode_by_type(o: typing.Any) -> typing.Any:
|
|
225
|
+
encoders_by_class_tuples: typing.Dict[typing.Callable[[typing.Any], typing.Any], typing.Tuple[typing.Any, ...]] = (
|
|
226
|
+
defaultdict(tuple)
|
|
227
|
+
)
|
|
194
228
|
for type_, encoder in encoders_by_type.items():
|
|
195
229
|
encoders_by_class_tuples[encoder] += (type_,)
|
|
196
230
|
|
|
@@ -201,49 +235,54 @@ def encode_by_type(o: Any) -> Any:
|
|
|
201
235
|
return encoder(o)
|
|
202
236
|
|
|
203
237
|
|
|
204
|
-
def update_forward_refs(model: Type["Model"], **localns: Any) -> None:
|
|
238
|
+
def update_forward_refs(model: typing.Type["Model"], **localns: typing.Any) -> None:
|
|
205
239
|
if IS_PYDANTIC_V2:
|
|
206
|
-
model.model_rebuild(raise_errors=False) # type: ignore
|
|
240
|
+
model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2
|
|
207
241
|
else:
|
|
208
242
|
model.update_forward_refs(**localns)
|
|
209
243
|
|
|
210
244
|
|
|
211
245
|
# Mirrors Pydantic's internal typing
|
|
212
|
-
AnyCallable = Callable[..., Any]
|
|
246
|
+
AnyCallable = typing.Callable[..., typing.Any]
|
|
213
247
|
|
|
214
248
|
|
|
215
249
|
def universal_root_validator(
|
|
216
250
|
pre: bool = False,
|
|
217
|
-
) -> Callable[[AnyCallable], AnyCallable]:
|
|
251
|
+
) -> typing.Callable[[AnyCallable], AnyCallable]:
|
|
218
252
|
def decorator(func: AnyCallable) -> AnyCallable:
|
|
219
253
|
if IS_PYDANTIC_V2:
|
|
220
|
-
return
|
|
221
|
-
|
|
254
|
+
return pydantic.model_validator(mode="before" if pre else "after")(func) # type: ignore # Pydantic v2
|
|
255
|
+
else:
|
|
256
|
+
return pydantic.root_validator(pre=pre)(func) # type: ignore # Pydantic v1
|
|
222
257
|
|
|
223
258
|
return decorator
|
|
224
259
|
|
|
225
260
|
|
|
226
|
-
def universal_field_validator(field_name: str, pre: bool = False) -> Callable[[AnyCallable], AnyCallable]:
|
|
261
|
+
def universal_field_validator(field_name: str, pre: bool = False) -> typing.Callable[[AnyCallable], AnyCallable]:
|
|
227
262
|
def decorator(func: AnyCallable) -> AnyCallable:
|
|
228
263
|
if IS_PYDANTIC_V2:
|
|
229
|
-
return
|
|
230
|
-
|
|
264
|
+
return pydantic.field_validator(field_name, mode="before" if pre else "after")(func) # type: ignore # Pydantic v2
|
|
265
|
+
else:
|
|
266
|
+
return pydantic.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1
|
|
231
267
|
|
|
232
268
|
return decorator
|
|
233
269
|
|
|
234
270
|
|
|
235
|
-
PydanticField = Union[ModelField, pydantic.fields.FieldInfo]
|
|
271
|
+
PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo]
|
|
236
272
|
|
|
237
273
|
|
|
238
|
-
def _get_model_fields(
|
|
274
|
+
def _get_model_fields(
|
|
275
|
+
model: typing.Type["Model"],
|
|
276
|
+
) -> typing.Mapping[str, PydanticField]:
|
|
239
277
|
if IS_PYDANTIC_V2:
|
|
240
|
-
return
|
|
241
|
-
|
|
278
|
+
return model.model_fields # type: ignore # Pydantic v2
|
|
279
|
+
else:
|
|
280
|
+
return model.__fields__ # type: ignore # Pydantic v1
|
|
242
281
|
|
|
243
282
|
|
|
244
|
-
def _get_field_default(field: PydanticField) -> Any:
|
|
283
|
+
def _get_field_default(field: PydanticField) -> typing.Any:
|
|
245
284
|
try:
|
|
246
|
-
value = field.get_default() # type: ignore
|
|
285
|
+
value = field.get_default() # type: ignore # Pydantic < v1.10.15
|
|
247
286
|
except:
|
|
248
287
|
value = field.default
|
|
249
288
|
if IS_PYDANTIC_V2:
|
sarvamai/environment.py
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import enum
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class SarvamAIEnvironment:
|
|
7
|
-
PRODUCTION
|
|
8
|
-
|
|
9
|
-
def __init__(self, *, base: str, production: str):
|
|
10
|
-
self.base = base
|
|
11
|
-
self.production = production
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
SarvamAIEnvironment.PRODUCTION = SarvamAIEnvironment(base="https://api.sarvam.ai", production="wss://api.sarvam.ai")
|
|
6
|
+
class SarvamAIEnvironment(enum.Enum):
|
|
7
|
+
PRODUCTION = "https://api.sarvam.ai"
|
sarvamai/errors/__init__.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
3
|
from ..core.api_error import ApiError
|
|
4
|
+
import typing
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class BadRequestError(ApiError):
|
|
9
|
-
def __init__(self, body: typing.Optional[typing.Any]
|
|
10
|
-
super().__init__(status_code=400,
|
|
8
|
+
def __init__(self, body: typing.Optional[typing.Any]):
|
|
9
|
+
super().__init__(status_code=400, body=body)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
3
|
from ..core.api_error import ApiError
|
|
4
|
+
import typing
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class ForbiddenError(ApiError):
|
|
9
|
-
def __init__(self, body: typing.Optional[typing.Any]
|
|
10
|
-
super().__init__(status_code=403,
|
|
8
|
+
def __init__(self, body: typing.Optional[typing.Any]):
|
|
9
|
+
super().__init__(status_code=403, body=body)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
3
|
from ..core.api_error import ApiError
|
|
4
|
+
import typing
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class InternalServerError(ApiError):
|
|
9
|
-
def __init__(self, body: typing.Optional[typing.Any]
|
|
10
|
-
super().__init__(status_code=500,
|
|
8
|
+
def __init__(self, body: typing.Optional[typing.Any]):
|
|
9
|
+
super().__init__(status_code=500, body=body)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
3
|
from ..core.api_error import ApiError
|
|
6
4
|
from ..types.error_message import ErrorMessage
|
|
7
5
|
|
|
8
6
|
|
|
9
7
|
class ServiceUnavailableError(ApiError):
|
|
10
|
-
def __init__(self, body: ErrorMessage
|
|
11
|
-
super().__init__(status_code=503,
|
|
8
|
+
def __init__(self, body: ErrorMessage):
|
|
9
|
+
super().__init__(status_code=503, body=body)
|