mistralai 1.10.0__py3-none-any.whl → 1.11.1__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.
- mistralai/_hooks/tracing.py +28 -3
- mistralai/_version.py +3 -3
- mistralai/accesses.py +22 -12
- mistralai/agents.py +88 -44
- mistralai/basesdk.py +6 -0
- mistralai/chat.py +96 -40
- mistralai/classifiers.py +48 -23
- mistralai/conversations.py +186 -64
- mistralai/documents.py +72 -26
- mistralai/embeddings.py +24 -9
- mistralai/extra/README.md +1 -1
- mistralai/extra/mcp/auth.py +10 -11
- mistralai/extra/mcp/base.py +17 -16
- mistralai/extra/mcp/sse.py +13 -15
- mistralai/extra/mcp/stdio.py +5 -6
- mistralai/extra/observability/otel.py +47 -68
- mistralai/extra/run/context.py +33 -43
- mistralai/extra/run/result.py +29 -30
- mistralai/extra/run/tools.py +8 -9
- mistralai/extra/struct_chat.py +15 -8
- mistralai/extra/utils/response_format.py +5 -3
- mistralai/files.py +58 -24
- mistralai/fim.py +20 -12
- mistralai/httpclient.py +0 -1
- mistralai/jobs.py +65 -26
- mistralai/libraries.py +20 -10
- mistralai/mistral_agents.py +438 -30
- mistralai/mistral_jobs.py +62 -17
- mistralai/models/__init__.py +46 -1
- mistralai/models/agent.py +1 -1
- mistralai/models/agentconversation.py +1 -1
- mistralai/models/agenthandoffdoneevent.py +1 -1
- mistralai/models/agenthandoffentry.py +3 -2
- mistralai/models/agenthandoffstartedevent.py +1 -1
- mistralai/models/agents_api_v1_agents_get_versionop.py +21 -0
- mistralai/models/agents_api_v1_agents_list_versionsop.py +33 -0
- mistralai/models/agents_api_v1_agents_listop.py +5 -1
- mistralai/models/agents_api_v1_conversations_listop.py +1 -1
- mistralai/models/agentscompletionrequest.py +2 -5
- mistralai/models/agentscompletionstreamrequest.py +2 -5
- mistralai/models/archiveftmodelout.py +1 -1
- mistralai/models/assistantmessage.py +1 -1
- mistralai/models/audiochunk.py +1 -1
- mistralai/models/audioencoding.py +18 -0
- mistralai/models/audioformat.py +17 -0
- mistralai/models/basemodelcard.py +1 -1
- mistralai/models/batchjobin.py +18 -9
- mistralai/models/batchjobout.py +6 -1
- mistralai/models/batchjobsout.py +1 -1
- mistralai/models/batchrequest.py +48 -0
- mistralai/models/chatcompletionchoice.py +10 -5
- mistralai/models/chatcompletionrequest.py +2 -5
- mistralai/models/chatcompletionstreamrequest.py +2 -5
- mistralai/models/classificationrequest.py +37 -3
- mistralai/models/classifierdetailedjobout.py +4 -2
- mistralai/models/classifierftmodelout.py +3 -2
- mistralai/models/classifierjobout.py +4 -2
- mistralai/models/codeinterpretertool.py +1 -1
- mistralai/models/completiondetailedjobout.py +5 -2
- mistralai/models/completionftmodelout.py +3 -2
- mistralai/models/completionjobout.py +5 -2
- mistralai/models/completionresponsestreamchoice.py +9 -8
- mistralai/models/conversationappendrequest.py +4 -1
- mistralai/models/conversationappendstreamrequest.py +4 -1
- mistralai/models/conversationhistory.py +2 -1
- mistralai/models/conversationmessages.py +1 -1
- mistralai/models/conversationrequest.py +5 -1
- mistralai/models/conversationresponse.py +2 -1
- mistralai/models/conversationrestartrequest.py +4 -1
- mistralai/models/conversationrestartstreamrequest.py +4 -1
- mistralai/models/conversationstreamrequest.py +5 -1
- mistralai/models/documentlibrarytool.py +1 -1
- mistralai/models/documenturlchunk.py +1 -1
- mistralai/models/embeddingdtype.py +7 -1
- mistralai/models/embeddingrequest.py +11 -3
- mistralai/models/encodingformat.py +4 -1
- mistralai/models/entitytype.py +8 -1
- mistralai/models/filepurpose.py +8 -1
- mistralai/models/files_api_routes_list_filesop.py +4 -11
- mistralai/models/files_api_routes_upload_fileop.py +2 -6
- mistralai/models/fileschema.py +3 -5
- mistralai/models/finetuneablemodeltype.py +4 -1
- mistralai/models/ftclassifierlossfunction.py +4 -1
- mistralai/models/ftmodelcard.py +1 -1
- mistralai/models/functioncallentry.py +3 -2
- mistralai/models/functioncallevent.py +1 -1
- mistralai/models/functionresultentry.py +3 -2
- mistralai/models/functiontool.py +1 -1
- mistralai/models/githubrepositoryin.py +1 -1
- mistralai/models/githubrepositoryout.py +1 -1
- mistralai/models/httpvalidationerror.py +4 -2
- mistralai/models/imagegenerationtool.py +1 -1
- mistralai/models/imageurlchunk.py +1 -1
- mistralai/models/jobs_api_routes_batch_get_batch_jobop.py +40 -3
- mistralai/models/jobsout.py +1 -1
- mistralai/models/legacyjobmetadataout.py +1 -1
- mistralai/models/messageinputentry.py +9 -3
- mistralai/models/messageoutputentry.py +6 -3
- mistralai/models/messageoutputevent.py +4 -2
- mistralai/models/mistralerror.py +11 -7
- mistralai/models/mistralpromptmode.py +1 -1
- mistralai/models/modelconversation.py +1 -1
- mistralai/models/no_response_error.py +5 -1
- mistralai/models/ocrrequest.py +11 -1
- mistralai/models/ocrtableobject.py +4 -1
- mistralai/models/referencechunk.py +1 -1
- mistralai/models/requestsource.py +5 -1
- mistralai/models/responsedoneevent.py +1 -1
- mistralai/models/responseerrorevent.py +1 -1
- mistralai/models/responseformats.py +5 -1
- mistralai/models/responsestartedevent.py +1 -1
- mistralai/models/responsevalidationerror.py +2 -0
- mistralai/models/retrievefileout.py +3 -5
- mistralai/models/sampletype.py +7 -1
- mistralai/models/sdkerror.py +2 -0
- mistralai/models/shareenum.py +7 -1
- mistralai/models/sharingdelete.py +2 -4
- mistralai/models/sharingin.py +3 -5
- mistralai/models/source.py +8 -1
- mistralai/models/systemmessage.py +1 -1
- mistralai/models/textchunk.py +1 -1
- mistralai/models/thinkchunk.py +1 -1
- mistralai/models/timestampgranularity.py +1 -1
- mistralai/models/tool.py +2 -6
- mistralai/models/toolcall.py +2 -6
- mistralai/models/toolchoice.py +2 -6
- mistralai/models/toolchoiceenum.py +6 -1
- mistralai/models/toolexecutiondeltaevent.py +2 -1
- mistralai/models/toolexecutiondoneevent.py +2 -1
- mistralai/models/toolexecutionentry.py +4 -2
- mistralai/models/toolexecutionstartedevent.py +2 -1
- mistralai/models/toolfilechunk.py +13 -5
- mistralai/models/toolmessage.py +1 -1
- mistralai/models/toolreferencechunk.py +15 -5
- mistralai/models/tooltypes.py +1 -1
- mistralai/models/transcriptionsegmentchunk.py +1 -1
- mistralai/models/transcriptionstreamdone.py +1 -1
- mistralai/models/transcriptionstreamlanguage.py +1 -1
- mistralai/models/transcriptionstreamsegmentdelta.py +1 -1
- mistralai/models/transcriptionstreamtextdelta.py +1 -1
- mistralai/models/unarchiveftmodelout.py +1 -1
- mistralai/models/uploadfileout.py +3 -5
- mistralai/models/usermessage.py +1 -1
- mistralai/models/wandbintegration.py +1 -1
- mistralai/models/wandbintegrationout.py +1 -1
- mistralai/models/websearchpremiumtool.py +1 -1
- mistralai/models/websearchtool.py +1 -1
- mistralai/models_.py +24 -12
- mistralai/ocr.py +38 -10
- mistralai/sdk.py +2 -2
- mistralai/transcriptions.py +28 -12
- mistralai/types/basemodel.py +41 -3
- mistralai/utils/__init__.py +0 -3
- mistralai/utils/annotations.py +32 -8
- mistralai/utils/enums.py +60 -0
- mistralai/utils/forms.py +21 -10
- mistralai/utils/queryparams.py +14 -2
- mistralai/utils/requestbodies.py +3 -3
- mistralai/utils/retries.py +69 -5
- mistralai/utils/serializers.py +0 -20
- mistralai/utils/unmarshal_json_response.py +15 -1
- {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/METADATA +144 -159
- mistralai-1.11.1.dist-info/RECORD +495 -0
- {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/WHEEL +1 -1
- mistralai_azure/_version.py +3 -3
- mistralai_azure/basesdk.py +21 -5
- mistralai_azure/chat.py +82 -109
- mistralai_azure/httpclient.py +0 -1
- mistralai_azure/models/__init__.py +66 -4
- mistralai_azure/models/assistantmessage.py +1 -1
- mistralai_azure/models/chatcompletionchoice.py +10 -7
- mistralai_azure/models/chatcompletionrequest.py +24 -10
- mistralai_azure/models/chatcompletionstreamrequest.py +24 -10
- mistralai_azure/models/completionresponsestreamchoice.py +11 -7
- mistralai_azure/models/documenturlchunk.py +1 -1
- mistralai_azure/models/httpvalidationerror.py +15 -8
- mistralai_azure/models/imageurlchunk.py +1 -1
- mistralai_azure/models/mistralazureerror.py +30 -0
- mistralai_azure/models/mistralpromptmode.py +1 -1
- mistralai_azure/models/no_response_error.py +17 -0
- mistralai_azure/models/ocrpageobject.py +32 -5
- mistralai_azure/models/ocrrequest.py +20 -1
- mistralai_azure/models/ocrtableobject.py +34 -0
- mistralai_azure/models/prediction.py +4 -0
- mistralai_azure/models/referencechunk.py +1 -1
- mistralai_azure/models/responseformat.py +4 -2
- mistralai_azure/models/responseformats.py +5 -2
- mistralai_azure/models/responsevalidationerror.py +27 -0
- mistralai_azure/models/sdkerror.py +32 -14
- mistralai_azure/models/systemmessage.py +8 -4
- mistralai_azure/models/systemmessagecontentchunks.py +21 -0
- mistralai_azure/models/textchunk.py +1 -1
- mistralai_azure/models/thinkchunk.py +35 -0
- mistralai_azure/models/tool.py +2 -6
- mistralai_azure/models/toolcall.py +2 -6
- mistralai_azure/models/toolchoice.py +2 -6
- mistralai_azure/models/toolchoiceenum.py +6 -1
- mistralai_azure/models/toolmessage.py +1 -1
- mistralai_azure/models/tooltypes.py +1 -1
- mistralai_azure/models/usermessage.py +1 -1
- mistralai_azure/ocr.py +39 -40
- mistralai_azure/types/basemodel.py +41 -3
- mistralai_azure/utils/__init__.py +18 -8
- mistralai_azure/utils/annotations.py +32 -8
- mistralai_azure/utils/enums.py +60 -0
- mistralai_azure/utils/eventstreaming.py +10 -0
- mistralai_azure/utils/forms.py +21 -10
- mistralai_azure/utils/queryparams.py +14 -2
- mistralai_azure/utils/requestbodies.py +3 -3
- mistralai_azure/utils/retries.py +69 -5
- mistralai_azure/utils/serializers.py +3 -22
- mistralai_azure/utils/unmarshal_json_response.py +38 -0
- mistralai_gcp/_hooks/types.py +7 -0
- mistralai_gcp/_version.py +4 -4
- mistralai_gcp/basesdk.py +33 -25
- mistralai_gcp/chat.py +98 -109
- mistralai_gcp/fim.py +62 -85
- mistralai_gcp/httpclient.py +6 -17
- mistralai_gcp/models/__init__.py +321 -116
- mistralai_gcp/models/assistantmessage.py +2 -2
- mistralai_gcp/models/chatcompletionchoice.py +10 -7
- mistralai_gcp/models/chatcompletionrequest.py +38 -7
- mistralai_gcp/models/chatcompletionresponse.py +6 -6
- mistralai_gcp/models/chatcompletionstreamrequest.py +38 -7
- mistralai_gcp/models/completionresponsestreamchoice.py +12 -8
- mistralai_gcp/models/deltamessage.py +1 -1
- mistralai_gcp/models/fimcompletionrequest.py +9 -10
- mistralai_gcp/models/fimcompletionresponse.py +6 -6
- mistralai_gcp/models/fimcompletionstreamrequest.py +9 -10
- mistralai_gcp/models/httpvalidationerror.py +15 -8
- mistralai_gcp/models/imageurl.py +1 -1
- mistralai_gcp/models/imageurlchunk.py +1 -1
- mistralai_gcp/models/jsonschema.py +1 -1
- mistralai_gcp/models/mistralgcperror.py +30 -0
- mistralai_gcp/models/mistralpromptmode.py +8 -0
- mistralai_gcp/models/no_response_error.py +17 -0
- mistralai_gcp/models/prediction.py +4 -0
- mistralai_gcp/models/referencechunk.py +1 -1
- mistralai_gcp/models/responseformat.py +5 -3
- mistralai_gcp/models/responseformats.py +5 -2
- mistralai_gcp/models/responsevalidationerror.py +27 -0
- mistralai_gcp/models/sdkerror.py +32 -14
- mistralai_gcp/models/systemmessage.py +8 -4
- mistralai_gcp/models/systemmessagecontentchunks.py +21 -0
- mistralai_gcp/models/textchunk.py +1 -1
- mistralai_gcp/models/thinkchunk.py +35 -0
- mistralai_gcp/models/tool.py +2 -6
- mistralai_gcp/models/toolcall.py +2 -6
- mistralai_gcp/models/toolchoice.py +2 -6
- mistralai_gcp/models/toolchoiceenum.py +6 -1
- mistralai_gcp/models/toolmessage.py +2 -2
- mistralai_gcp/models/tooltypes.py +1 -1
- mistralai_gcp/models/usageinfo.py +71 -8
- mistralai_gcp/models/usermessage.py +2 -2
- mistralai_gcp/sdk.py +12 -10
- mistralai_gcp/sdkconfiguration.py +0 -7
- mistralai_gcp/types/basemodel.py +41 -3
- mistralai_gcp/utils/__init__.py +141 -46
- mistralai_gcp/utils/annotations.py +32 -8
- mistralai_gcp/utils/datetimes.py +23 -0
- mistralai_gcp/utils/enums.py +125 -25
- mistralai_gcp/utils/eventstreaming.py +10 -0
- mistralai_gcp/utils/forms.py +62 -30
- mistralai_gcp/utils/queryparams.py +14 -2
- mistralai_gcp/utils/requestbodies.py +3 -3
- mistralai_gcp/utils/retries.py +69 -5
- mistralai_gcp/utils/serializers.py +33 -23
- mistralai_gcp/utils/unmarshal_json_response.py +38 -0
- mistralai-1.10.0.dist-info/RECORD +0 -475
- {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/licenses/LICENSE +0 -0
mistralai_azure/utils/enums.py
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
4
|
import sys
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic_core import core_schema
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class OpenEnumMeta(enum.EnumMeta):
|
|
7
11
|
# The __call__ method `boundary` kwarg was added in 3.11 and must be present
|
|
@@ -72,3 +76,59 @@ class OpenEnumMeta(enum.EnumMeta):
|
|
|
72
76
|
)
|
|
73
77
|
except ValueError:
|
|
74
78
|
return value
|
|
79
|
+
|
|
80
|
+
def __new__(mcs, name, bases, namespace, **kwargs):
|
|
81
|
+
cls = super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
82
|
+
|
|
83
|
+
# Add __get_pydantic_core_schema__ to make open enums work correctly
|
|
84
|
+
# in union discrimination. In strict mode (used by Pydantic for unions),
|
|
85
|
+
# only known enum values match. In lax mode, unknown values are accepted.
|
|
86
|
+
def __get_pydantic_core_schema__(
|
|
87
|
+
cls_inner: Any, _source_type: Any, _handler: Any
|
|
88
|
+
) -> core_schema.CoreSchema:
|
|
89
|
+
# Create a validator that only accepts known enum values (for strict mode)
|
|
90
|
+
def validate_strict(v: Any) -> Any:
|
|
91
|
+
if isinstance(v, cls_inner):
|
|
92
|
+
return v
|
|
93
|
+
# Use the parent EnumMeta's __call__ which raises ValueError for unknown values
|
|
94
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
95
|
+
|
|
96
|
+
# Create a lax validator that accepts unknown values
|
|
97
|
+
def validate_lax(v: Any) -> Any:
|
|
98
|
+
if isinstance(v, cls_inner):
|
|
99
|
+
return v
|
|
100
|
+
try:
|
|
101
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
102
|
+
except ValueError:
|
|
103
|
+
# Return the raw value for unknown enum values
|
|
104
|
+
return v
|
|
105
|
+
|
|
106
|
+
# Determine the base type schema (str or int)
|
|
107
|
+
is_int_enum = False
|
|
108
|
+
for base in cls_inner.__mro__:
|
|
109
|
+
if base is int:
|
|
110
|
+
is_int_enum = True
|
|
111
|
+
break
|
|
112
|
+
if base is str:
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
base_schema = (
|
|
116
|
+
core_schema.int_schema()
|
|
117
|
+
if is_int_enum
|
|
118
|
+
else core_schema.str_schema()
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Use lax_or_strict_schema:
|
|
122
|
+
# - strict mode: only known enum values match (raises ValueError for unknown)
|
|
123
|
+
# - lax mode: accept any value, return enum member or raw value
|
|
124
|
+
return core_schema.lax_or_strict_schema(
|
|
125
|
+
lax_schema=core_schema.chain_schema(
|
|
126
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_lax)]
|
|
127
|
+
),
|
|
128
|
+
strict_schema=core_schema.chain_schema(
|
|
129
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_strict)]
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
setattr(cls, "__get_pydantic_core_schema__", classmethod(__get_pydantic_core_schema__))
|
|
134
|
+
return cls
|
|
@@ -17,6 +17,9 @@ T = TypeVar("T")
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class EventStream(Generic[T]):
|
|
20
|
+
# Holds a reference to the SDK client to avoid it being garbage collected
|
|
21
|
+
# and cause termination of the underlying httpx client.
|
|
22
|
+
client_ref: Optional[object]
|
|
20
23
|
response: httpx.Response
|
|
21
24
|
generator: Generator[T, None, None]
|
|
22
25
|
|
|
@@ -25,9 +28,11 @@ class EventStream(Generic[T]):
|
|
|
25
28
|
response: httpx.Response,
|
|
26
29
|
decoder: Callable[[str], T],
|
|
27
30
|
sentinel: Optional[str] = None,
|
|
31
|
+
client_ref: Optional[object] = None,
|
|
28
32
|
):
|
|
29
33
|
self.response = response
|
|
30
34
|
self.generator = stream_events(response, decoder, sentinel)
|
|
35
|
+
self.client_ref = client_ref
|
|
31
36
|
|
|
32
37
|
def __iter__(self):
|
|
33
38
|
return self
|
|
@@ -43,6 +48,9 @@ class EventStream(Generic[T]):
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
class EventStreamAsync(Generic[T]):
|
|
51
|
+
# Holds a reference to the SDK client to avoid it being garbage collected
|
|
52
|
+
# and cause termination of the underlying httpx client.
|
|
53
|
+
client_ref: Optional[object]
|
|
46
54
|
response: httpx.Response
|
|
47
55
|
generator: AsyncGenerator[T, None]
|
|
48
56
|
|
|
@@ -51,9 +59,11 @@ class EventStreamAsync(Generic[T]):
|
|
|
51
59
|
response: httpx.Response,
|
|
52
60
|
decoder: Callable[[str], T],
|
|
53
61
|
sentinel: Optional[str] = None,
|
|
62
|
+
client_ref: Optional[object] = None,
|
|
54
63
|
):
|
|
55
64
|
self.response = response
|
|
56
65
|
self.generator = stream_events_async(response, decoder, sentinel)
|
|
66
|
+
self.client_ref = client_ref
|
|
57
67
|
|
|
58
68
|
def __aiter__(self):
|
|
59
69
|
return self
|
mistralai_azure/utils/forms.py
CHANGED
|
@@ -142,16 +142,21 @@ def serialize_multipart_form(
|
|
|
142
142
|
if field_metadata.file:
|
|
143
143
|
if isinstance(val, List):
|
|
144
144
|
# Handle array of files
|
|
145
|
+
array_field_name = f_name + "[]"
|
|
145
146
|
for file_obj in val:
|
|
146
147
|
if not _is_set(file_obj):
|
|
147
148
|
continue
|
|
148
|
-
|
|
149
|
-
file_name, content, content_type = _extract_file_properties(
|
|
149
|
+
|
|
150
|
+
file_name, content, content_type = _extract_file_properties(
|
|
151
|
+
file_obj
|
|
152
|
+
)
|
|
150
153
|
|
|
151
154
|
if content_type is not None:
|
|
152
|
-
files.append(
|
|
155
|
+
files.append(
|
|
156
|
+
(array_field_name, (file_name, content, content_type))
|
|
157
|
+
)
|
|
153
158
|
else:
|
|
154
|
-
files.append((
|
|
159
|
+
files.append((array_field_name, (file_name, content)))
|
|
155
160
|
else:
|
|
156
161
|
# Handle single file
|
|
157
162
|
file_name, content, content_type = _extract_file_properties(val)
|
|
@@ -161,11 +166,16 @@ def serialize_multipart_form(
|
|
|
161
166
|
else:
|
|
162
167
|
files.append((f_name, (file_name, content)))
|
|
163
168
|
elif field_metadata.json:
|
|
164
|
-
files.append(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
files.append(
|
|
170
|
+
(
|
|
171
|
+
f_name,
|
|
172
|
+
(
|
|
173
|
+
None,
|
|
174
|
+
marshal_json(val, request_field_types[name]),
|
|
175
|
+
"application/json",
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
)
|
|
169
179
|
else:
|
|
170
180
|
if isinstance(val, List):
|
|
171
181
|
values = []
|
|
@@ -175,7 +185,8 @@ def serialize_multipart_form(
|
|
|
175
185
|
continue
|
|
176
186
|
values.append(_val_to_string(value))
|
|
177
187
|
|
|
178
|
-
|
|
188
|
+
array_field_name = f_name + "[]"
|
|
189
|
+
form[array_field_name] = values
|
|
179
190
|
else:
|
|
180
191
|
form[f_name] = _val_to_string(val)
|
|
181
192
|
return media_type, form, files
|
|
@@ -27,12 +27,13 @@ from .forms import _populate_form
|
|
|
27
27
|
def get_query_params(
|
|
28
28
|
query_params: Any,
|
|
29
29
|
gbls: Optional[Any] = None,
|
|
30
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
30
31
|
) -> Dict[str, List[str]]:
|
|
31
32
|
params: Dict[str, List[str]] = {}
|
|
32
33
|
|
|
33
|
-
globals_already_populated = _populate_query_params(query_params, gbls, params, [])
|
|
34
|
+
globals_already_populated = _populate_query_params(query_params, gbls, params, [], allow_empty_value)
|
|
34
35
|
if _is_set(gbls):
|
|
35
|
-
_populate_query_params(gbls, None, params, globals_already_populated)
|
|
36
|
+
_populate_query_params(gbls, None, params, globals_already_populated, allow_empty_value)
|
|
36
37
|
|
|
37
38
|
return params
|
|
38
39
|
|
|
@@ -42,6 +43,7 @@ def _populate_query_params(
|
|
|
42
43
|
gbls: Any,
|
|
43
44
|
query_param_values: Dict[str, List[str]],
|
|
44
45
|
skip_fields: List[str],
|
|
46
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
45
47
|
) -> List[str]:
|
|
46
48
|
globals_already_populated: List[str] = []
|
|
47
49
|
|
|
@@ -69,6 +71,16 @@ def _populate_query_params(
|
|
|
69
71
|
globals_already_populated.append(name)
|
|
70
72
|
|
|
71
73
|
f_name = field.alias if field.alias is not None else name
|
|
74
|
+
|
|
75
|
+
allow_empty_set = set(allow_empty_value or [])
|
|
76
|
+
should_include_empty = f_name in allow_empty_set and (
|
|
77
|
+
value is None or value == [] or value == ""
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if should_include_empty:
|
|
81
|
+
query_param_values[f_name] = [""]
|
|
82
|
+
continue
|
|
83
|
+
|
|
72
84
|
serialization = metadata.serialization
|
|
73
85
|
if serialization is not None:
|
|
74
86
|
serialized_parms = _get_serialized_params(
|
|
@@ -44,15 +44,15 @@ def serialize_request_body(
|
|
|
44
44
|
|
|
45
45
|
serialized_request_body = SerializedRequestBody(media_type)
|
|
46
46
|
|
|
47
|
-
if re.match(r"(application|text)
|
|
47
|
+
if re.match(r"^(application|text)\/([^+]+\+)*json.*", media_type) is not None:
|
|
48
48
|
serialized_request_body.content = marshal_json(request_body, request_body_type)
|
|
49
|
-
elif re.match(r"multipart\/.*", media_type) is not None:
|
|
49
|
+
elif re.match(r"^multipart\/.*", media_type) is not None:
|
|
50
50
|
(
|
|
51
51
|
serialized_request_body.media_type,
|
|
52
52
|
serialized_request_body.data,
|
|
53
53
|
serialized_request_body.files,
|
|
54
54
|
) = serialize_multipart_form(media_type, request_body)
|
|
55
|
-
elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None:
|
|
55
|
+
elif re.match(r"^application\/x-www-form-urlencoded.*", media_type) is not None:
|
|
56
56
|
serialized_request_body.data = serialize_form_data(request_body)
|
|
57
57
|
elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)):
|
|
58
58
|
serialized_request_body.content = request_body
|
mistralai_azure/utils/retries.py
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import random
|
|
5
5
|
import time
|
|
6
|
-
from
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from email.utils import parsedate_to_datetime
|
|
8
|
+
from typing import List, Optional
|
|
7
9
|
|
|
8
10
|
import httpx
|
|
9
11
|
|
|
@@ -51,9 +53,11 @@ class Retries:
|
|
|
51
53
|
|
|
52
54
|
class TemporaryError(Exception):
|
|
53
55
|
response: httpx.Response
|
|
56
|
+
retry_after: Optional[int]
|
|
54
57
|
|
|
55
58
|
def __init__(self, response: httpx.Response):
|
|
56
59
|
self.response = response
|
|
60
|
+
self.retry_after = _parse_retry_after_header(response)
|
|
57
61
|
|
|
58
62
|
|
|
59
63
|
class PermanentError(Exception):
|
|
@@ -63,6 +67,62 @@ class PermanentError(Exception):
|
|
|
63
67
|
self.inner = inner
|
|
64
68
|
|
|
65
69
|
|
|
70
|
+
def _parse_retry_after_header(response: httpx.Response) -> Optional[int]:
|
|
71
|
+
"""Parse Retry-After header from response.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Retry interval in milliseconds, or None if header is missing or invalid.
|
|
75
|
+
"""
|
|
76
|
+
retry_after_header = response.headers.get("retry-after")
|
|
77
|
+
if not retry_after_header:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
seconds = float(retry_after_header)
|
|
82
|
+
return round(seconds * 1000)
|
|
83
|
+
except ValueError:
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
retry_date = parsedate_to_datetime(retry_after_header)
|
|
88
|
+
delta = (retry_date - datetime.now(retry_date.tzinfo)).total_seconds()
|
|
89
|
+
return round(max(0, delta) * 1000)
|
|
90
|
+
except (ValueError, TypeError):
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _get_sleep_interval(
|
|
97
|
+
exception: Exception,
|
|
98
|
+
initial_interval: int,
|
|
99
|
+
max_interval: int,
|
|
100
|
+
exponent: float,
|
|
101
|
+
retries: int,
|
|
102
|
+
) -> float:
|
|
103
|
+
"""Get sleep interval for retry with exponential backoff.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
exception: The exception that triggered the retry.
|
|
107
|
+
initial_interval: Initial retry interval in milliseconds.
|
|
108
|
+
max_interval: Maximum retry interval in milliseconds.
|
|
109
|
+
exponent: Base for exponential backoff calculation.
|
|
110
|
+
retries: Current retry attempt count.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Sleep interval in seconds.
|
|
114
|
+
"""
|
|
115
|
+
if (
|
|
116
|
+
isinstance(exception, TemporaryError)
|
|
117
|
+
and exception.retry_after is not None
|
|
118
|
+
and exception.retry_after > 0
|
|
119
|
+
):
|
|
120
|
+
return exception.retry_after / 1000
|
|
121
|
+
|
|
122
|
+
sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
|
|
123
|
+
return min(sleep, max_interval / 1000)
|
|
124
|
+
|
|
125
|
+
|
|
66
126
|
def retry(func, retries: Retries):
|
|
67
127
|
if retries.config.strategy == "backoff":
|
|
68
128
|
|
|
@@ -183,8 +243,10 @@ def retry_with_backoff(
|
|
|
183
243
|
return exception.response
|
|
184
244
|
|
|
185
245
|
raise
|
|
186
|
-
|
|
187
|
-
sleep =
|
|
246
|
+
|
|
247
|
+
sleep = _get_sleep_interval(
|
|
248
|
+
exception, initial_interval, max_interval, exponent, retries
|
|
249
|
+
)
|
|
188
250
|
time.sleep(sleep)
|
|
189
251
|
retries += 1
|
|
190
252
|
|
|
@@ -211,7 +273,9 @@ async def retry_with_backoff_async(
|
|
|
211
273
|
return exception.response
|
|
212
274
|
|
|
213
275
|
raise
|
|
214
|
-
|
|
215
|
-
sleep =
|
|
276
|
+
|
|
277
|
+
sleep = _get_sleep_interval(
|
|
278
|
+
exception, initial_interval, max_interval, exponent, retries
|
|
279
|
+
)
|
|
216
280
|
await asyncio.sleep(sleep)
|
|
217
281
|
retries += 1
|
|
@@ -102,26 +102,6 @@ def validate_int(b):
|
|
|
102
102
|
return int(b)
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
def validate_open_enum(is_int: bool):
|
|
106
|
-
def validate(e):
|
|
107
|
-
if e is None:
|
|
108
|
-
return None
|
|
109
|
-
|
|
110
|
-
if isinstance(e, Unset):
|
|
111
|
-
return e
|
|
112
|
-
|
|
113
|
-
if is_int:
|
|
114
|
-
if not isinstance(e, int):
|
|
115
|
-
raise ValueError("Expected int")
|
|
116
|
-
else:
|
|
117
|
-
if not isinstance(e, str):
|
|
118
|
-
raise ValueError("Expected string")
|
|
119
|
-
|
|
120
|
-
return e
|
|
121
|
-
|
|
122
|
-
return validate
|
|
123
|
-
|
|
124
|
-
|
|
125
105
|
def validate_const(v):
|
|
126
106
|
def validate(c):
|
|
127
107
|
# Optional[T] is a Union[T, None]
|
|
@@ -192,7 +172,9 @@ def is_union(obj: object) -> bool:
|
|
|
192
172
|
"""
|
|
193
173
|
Returns True if the given object is a typing.Union or typing_extensions.Union.
|
|
194
174
|
"""
|
|
195
|
-
return any(
|
|
175
|
+
return any(
|
|
176
|
+
obj is typing_obj for typing_obj in _get_typing_objects_by_name_of("Union")
|
|
177
|
+
)
|
|
196
178
|
|
|
197
179
|
|
|
198
180
|
def stream_to_text(stream: httpx.Response) -> str:
|
|
@@ -245,4 +227,3 @@ def _get_typing_objects_by_name_of(name: str) -> Tuple[Any, ...]:
|
|
|
245
227
|
f"Neither typing nor typing_extensions has an object called {name!r}"
|
|
246
228
|
)
|
|
247
229
|
return result
|
|
248
|
-
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional, Type, TypeVar, overload
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from .serializers import unmarshal_json
|
|
8
|
+
from mistralai_azure import models
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@overload
|
|
14
|
+
def unmarshal_json_response(
|
|
15
|
+
typ: Type[T], http_res: httpx.Response, body: Optional[str] = None
|
|
16
|
+
) -> T: ...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@overload
|
|
20
|
+
def unmarshal_json_response(
|
|
21
|
+
typ: Any, http_res: httpx.Response, body: Optional[str] = None
|
|
22
|
+
) -> Any: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def unmarshal_json_response(
|
|
26
|
+
typ: Any, http_res: httpx.Response, body: Optional[str] = None
|
|
27
|
+
) -> Any:
|
|
28
|
+
if body is None:
|
|
29
|
+
body = http_res.text
|
|
30
|
+
try:
|
|
31
|
+
return unmarshal_json(body, typ)
|
|
32
|
+
except Exception as e:
|
|
33
|
+
raise models.ResponseValidationError(
|
|
34
|
+
"Response validation failed",
|
|
35
|
+
http_res,
|
|
36
|
+
e,
|
|
37
|
+
body,
|
|
38
|
+
) from e
|
mistralai_gcp/_hooks/types.py
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
import httpx
|
|
5
5
|
from mistralai_gcp.httpclient import HttpClient
|
|
6
|
+
from mistralai_gcp.sdkconfiguration import SDKConfiguration
|
|
6
7
|
from typing import Any, Callable, List, Optional, Tuple, Union
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class HookContext:
|
|
11
|
+
config: SDKConfiguration
|
|
10
12
|
base_url: str
|
|
11
13
|
operation_id: str
|
|
12
14
|
oauth2_scopes: Optional[List[str]] = None
|
|
@@ -14,11 +16,13 @@ class HookContext:
|
|
|
14
16
|
|
|
15
17
|
def __init__(
|
|
16
18
|
self,
|
|
19
|
+
config: SDKConfiguration,
|
|
17
20
|
base_url: str,
|
|
18
21
|
operation_id: str,
|
|
19
22
|
oauth2_scopes: Optional[List[str]],
|
|
20
23
|
security_source: Optional[Union[Any, Callable[[], Any]]],
|
|
21
24
|
):
|
|
25
|
+
self.config = config
|
|
22
26
|
self.base_url = base_url
|
|
23
27
|
self.operation_id = operation_id
|
|
24
28
|
self.oauth2_scopes = oauth2_scopes
|
|
@@ -28,6 +32,7 @@ class HookContext:
|
|
|
28
32
|
class BeforeRequestContext(HookContext):
|
|
29
33
|
def __init__(self, hook_ctx: HookContext):
|
|
30
34
|
super().__init__(
|
|
35
|
+
hook_ctx.config,
|
|
31
36
|
hook_ctx.base_url,
|
|
32
37
|
hook_ctx.operation_id,
|
|
33
38
|
hook_ctx.oauth2_scopes,
|
|
@@ -38,6 +43,7 @@ class BeforeRequestContext(HookContext):
|
|
|
38
43
|
class AfterSuccessContext(HookContext):
|
|
39
44
|
def __init__(self, hook_ctx: HookContext):
|
|
40
45
|
super().__init__(
|
|
46
|
+
hook_ctx.config,
|
|
41
47
|
hook_ctx.base_url,
|
|
42
48
|
hook_ctx.operation_id,
|
|
43
49
|
hook_ctx.oauth2_scopes,
|
|
@@ -48,6 +54,7 @@ class AfterSuccessContext(HookContext):
|
|
|
48
54
|
class AfterErrorContext(HookContext):
|
|
49
55
|
def __init__(self, hook_ctx: HookContext):
|
|
50
56
|
super().__init__(
|
|
57
|
+
hook_ctx.config,
|
|
51
58
|
hook_ctx.base_url,
|
|
52
59
|
hook_ctx.operation_id,
|
|
53
60
|
hook_ctx.oauth2_scopes,
|
mistralai_gcp/_version.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import importlib.metadata
|
|
4
4
|
|
|
5
5
|
__title__: str = "mistralai-gcp"
|
|
6
|
-
__version__: str = "1.
|
|
7
|
-
__openapi_doc_version__: str = "0.0
|
|
8
|
-
__gen_version__: str = "2.
|
|
9
|
-
__user_agent__: str = "speakeasy-sdk/python 1.
|
|
6
|
+
__version__: str = "1.8.0"
|
|
7
|
+
__openapi_doc_version__: str = "1.0.0"
|
|
8
|
+
__gen_version__: str = "2.794.1"
|
|
9
|
+
__user_agent__: str = "speakeasy-sdk/python 1.8.0 2.794.1 1.0.0 mistralai-gcp"
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
if __package__ is not None:
|
mistralai_gcp/basesdk.py
CHANGED
|
@@ -15,9 +15,19 @@ from urllib.parse import parse_qs, urlparse
|
|
|
15
15
|
|
|
16
16
|
class BaseSDK:
|
|
17
17
|
sdk_configuration: SDKConfiguration
|
|
18
|
+
parent_ref: Optional[object] = None
|
|
19
|
+
"""
|
|
20
|
+
Reference to the root SDK instance, if any. This will prevent it from
|
|
21
|
+
being garbage collected while there are active streams.
|
|
22
|
+
"""
|
|
18
23
|
|
|
19
|
-
def __init__(
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
sdk_config: SDKConfiguration,
|
|
27
|
+
parent_ref: Optional[object] = None,
|
|
28
|
+
) -> None:
|
|
20
29
|
self.sdk_configuration = sdk_config
|
|
30
|
+
self.parent_ref = parent_ref
|
|
21
31
|
|
|
22
32
|
def _get_url(self, base_url, url_variables):
|
|
23
33
|
sdk_url, sdk_variables = self.sdk_configuration.get_server_details()
|
|
@@ -50,6 +60,7 @@ class BaseSDK:
|
|
|
50
60
|
] = None,
|
|
51
61
|
url_override: Optional[str] = None,
|
|
52
62
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
63
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
53
64
|
) -> httpx.Request:
|
|
54
65
|
client = self.sdk_configuration.async_client
|
|
55
66
|
return self._build_request_with_client(
|
|
@@ -70,6 +81,7 @@ class BaseSDK:
|
|
|
70
81
|
get_serialized_body,
|
|
71
82
|
url_override,
|
|
72
83
|
http_headers,
|
|
84
|
+
allow_empty_value,
|
|
73
85
|
)
|
|
74
86
|
|
|
75
87
|
def _build_request(
|
|
@@ -92,6 +104,7 @@ class BaseSDK:
|
|
|
92
104
|
] = None,
|
|
93
105
|
url_override: Optional[str] = None,
|
|
94
106
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
107
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
95
108
|
) -> httpx.Request:
|
|
96
109
|
client = self.sdk_configuration.client
|
|
97
110
|
return self._build_request_with_client(
|
|
@@ -112,6 +125,7 @@ class BaseSDK:
|
|
|
112
125
|
get_serialized_body,
|
|
113
126
|
url_override,
|
|
114
127
|
http_headers,
|
|
128
|
+
allow_empty_value,
|
|
115
129
|
)
|
|
116
130
|
|
|
117
131
|
def _build_request_with_client(
|
|
@@ -135,6 +149,7 @@ class BaseSDK:
|
|
|
135
149
|
] = None,
|
|
136
150
|
url_override: Optional[str] = None,
|
|
137
151
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
152
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
138
153
|
) -> httpx.Request:
|
|
139
154
|
query_params = {}
|
|
140
155
|
|
|
@@ -150,6 +165,7 @@ class BaseSDK:
|
|
|
150
165
|
query_params = utils.get_query_params(
|
|
151
166
|
request if request_has_query_params else None,
|
|
152
167
|
_globals if request_has_query_params else None,
|
|
168
|
+
allow_empty_value,
|
|
153
169
|
)
|
|
154
170
|
else:
|
|
155
171
|
# Pick up the query parameter from the override so they can be
|
|
@@ -218,12 +234,12 @@ class BaseSDK:
|
|
|
218
234
|
client = self.sdk_configuration.client
|
|
219
235
|
logger = self.sdk_configuration.debug_logger
|
|
220
236
|
|
|
237
|
+
hooks = self.sdk_configuration.__dict__["_hooks"]
|
|
238
|
+
|
|
221
239
|
def do():
|
|
222
240
|
http_res = None
|
|
223
241
|
try:
|
|
224
|
-
req =
|
|
225
|
-
BeforeRequestContext(hook_ctx), request
|
|
226
|
-
)
|
|
242
|
+
req = hooks.before_request(BeforeRequestContext(hook_ctx), request)
|
|
227
243
|
logger.debug(
|
|
228
244
|
"Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
|
229
245
|
req.method,
|
|
@@ -237,16 +253,14 @@ class BaseSDK:
|
|
|
237
253
|
|
|
238
254
|
http_res = client.send(req, stream=stream)
|
|
239
255
|
except Exception as e:
|
|
240
|
-
_, e =
|
|
241
|
-
AfterErrorContext(hook_ctx), None, e
|
|
242
|
-
)
|
|
256
|
+
_, e = hooks.after_error(AfterErrorContext(hook_ctx), None, e)
|
|
243
257
|
if e is not None:
|
|
244
258
|
logger.debug("Request Exception", exc_info=True)
|
|
245
259
|
raise e
|
|
246
260
|
|
|
247
261
|
if http_res is None:
|
|
248
262
|
logger.debug("Raising no response SDK error")
|
|
249
|
-
raise models.
|
|
263
|
+
raise models.NoResponseError("No response received")
|
|
250
264
|
|
|
251
265
|
logger.debug(
|
|
252
266
|
"Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
|
@@ -257,7 +271,7 @@ class BaseSDK:
|
|
|
257
271
|
)
|
|
258
272
|
|
|
259
273
|
if utils.match_status_codes(error_status_codes, http_res.status_code):
|
|
260
|
-
result, err =
|
|
274
|
+
result, err = hooks.after_error(
|
|
261
275
|
AfterErrorContext(hook_ctx), http_res, None
|
|
262
276
|
)
|
|
263
277
|
if err is not None:
|
|
@@ -267,7 +281,7 @@ class BaseSDK:
|
|
|
267
281
|
http_res = result
|
|
268
282
|
else:
|
|
269
283
|
logger.debug("Raising unexpected SDK error")
|
|
270
|
-
raise models.SDKError("Unexpected error occurred")
|
|
284
|
+
raise models.SDKError("Unexpected error occurred", http_res)
|
|
271
285
|
|
|
272
286
|
return http_res
|
|
273
287
|
|
|
@@ -277,9 +291,7 @@ class BaseSDK:
|
|
|
277
291
|
http_res = do()
|
|
278
292
|
|
|
279
293
|
if not utils.match_status_codes(error_status_codes, http_res.status_code):
|
|
280
|
-
http_res =
|
|
281
|
-
AfterSuccessContext(hook_ctx), http_res
|
|
282
|
-
)
|
|
294
|
+
http_res = hooks.after_success(AfterSuccessContext(hook_ctx), http_res)
|
|
283
295
|
|
|
284
296
|
return http_res
|
|
285
297
|
|
|
@@ -294,12 +306,12 @@ class BaseSDK:
|
|
|
294
306
|
client = self.sdk_configuration.async_client
|
|
295
307
|
logger = self.sdk_configuration.debug_logger
|
|
296
308
|
|
|
309
|
+
hooks = self.sdk_configuration.__dict__["_hooks"]
|
|
310
|
+
|
|
297
311
|
async def do():
|
|
298
312
|
http_res = None
|
|
299
313
|
try:
|
|
300
|
-
req =
|
|
301
|
-
BeforeRequestContext(hook_ctx), request
|
|
302
|
-
)
|
|
314
|
+
req = hooks.before_request(BeforeRequestContext(hook_ctx), request)
|
|
303
315
|
logger.debug(
|
|
304
316
|
"Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
|
305
317
|
req.method,
|
|
@@ -313,16 +325,14 @@ class BaseSDK:
|
|
|
313
325
|
|
|
314
326
|
http_res = await client.send(req, stream=stream)
|
|
315
327
|
except Exception as e:
|
|
316
|
-
_, e =
|
|
317
|
-
AfterErrorContext(hook_ctx), None, e
|
|
318
|
-
)
|
|
328
|
+
_, e = hooks.after_error(AfterErrorContext(hook_ctx), None, e)
|
|
319
329
|
if e is not None:
|
|
320
330
|
logger.debug("Request Exception", exc_info=True)
|
|
321
331
|
raise e
|
|
322
332
|
|
|
323
333
|
if http_res is None:
|
|
324
334
|
logger.debug("Raising no response SDK error")
|
|
325
|
-
raise models.
|
|
335
|
+
raise models.NoResponseError("No response received")
|
|
326
336
|
|
|
327
337
|
logger.debug(
|
|
328
338
|
"Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
|
@@ -333,7 +343,7 @@ class BaseSDK:
|
|
|
333
343
|
)
|
|
334
344
|
|
|
335
345
|
if utils.match_status_codes(error_status_codes, http_res.status_code):
|
|
336
|
-
result, err =
|
|
346
|
+
result, err = hooks.after_error(
|
|
337
347
|
AfterErrorContext(hook_ctx), http_res, None
|
|
338
348
|
)
|
|
339
349
|
if err is not None:
|
|
@@ -343,7 +353,7 @@ class BaseSDK:
|
|
|
343
353
|
http_res = result
|
|
344
354
|
else:
|
|
345
355
|
logger.debug("Raising unexpected SDK error")
|
|
346
|
-
raise models.SDKError("Unexpected error occurred")
|
|
356
|
+
raise models.SDKError("Unexpected error occurred", http_res)
|
|
347
357
|
|
|
348
358
|
return http_res
|
|
349
359
|
|
|
@@ -355,8 +365,6 @@ class BaseSDK:
|
|
|
355
365
|
http_res = await do()
|
|
356
366
|
|
|
357
367
|
if not utils.match_status_codes(error_status_codes, http_res.status_code):
|
|
358
|
-
http_res =
|
|
359
|
-
AfterSuccessContext(hook_ctx), http_res
|
|
360
|
-
)
|
|
368
|
+
http_res = hooks.after_success(AfterSuccessContext(hook_ctx), http_res)
|
|
361
369
|
|
|
362
370
|
return http_res
|