mistralai 1.9.7__py3-none-any.whl → 1.9.9__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.
Files changed (41) hide show
  1. mistralai/_version.py +2 -2
  2. {mistralai-1.9.7.dist-info → mistralai-1.9.9.dist-info}/METADATA +1 -1
  3. {mistralai-1.9.7.dist-info → mistralai-1.9.9.dist-info}/RECORD +41 -30
  4. mistralai_azure/_hooks/types.py +7 -0
  5. mistralai_azure/_version.py +3 -3
  6. mistralai_azure/basesdk.py +12 -20
  7. mistralai_azure/chat.py +16 -0
  8. mistralai_azure/httpclient.py +6 -16
  9. mistralai_azure/models/__init__.py +298 -103
  10. mistralai_azure/models/assistantmessage.py +1 -1
  11. mistralai_azure/models/chatcompletionrequest.py +20 -3
  12. mistralai_azure/models/chatcompletionresponse.py +6 -6
  13. mistralai_azure/models/chatcompletionstreamrequest.py +20 -3
  14. mistralai_azure/models/completionresponsestreamchoice.py +1 -1
  15. mistralai_azure/models/deltamessage.py +1 -1
  16. mistralai_azure/models/documenturlchunk.py +62 -0
  17. mistralai_azure/models/filechunk.py +23 -0
  18. mistralai_azure/models/imageurl.py +1 -1
  19. mistralai_azure/models/jsonschema.py +1 -1
  20. mistralai_azure/models/mistralpromptmode.py +8 -0
  21. mistralai_azure/models/ocrimageobject.py +89 -0
  22. mistralai_azure/models/ocrpagedimensions.py +25 -0
  23. mistralai_azure/models/ocrpageobject.py +64 -0
  24. mistralai_azure/models/ocrrequest.py +120 -0
  25. mistralai_azure/models/ocrresponse.py +68 -0
  26. mistralai_azure/models/ocrusageinfo.py +57 -0
  27. mistralai_azure/models/responseformat.py +1 -1
  28. mistralai_azure/models/toolmessage.py +1 -1
  29. mistralai_azure/models/usageinfo.py +71 -8
  30. mistralai_azure/models/usermessage.py +1 -1
  31. mistralai_azure/ocr.py +271 -0
  32. mistralai_azure/sdk.py +45 -17
  33. mistralai_azure/sdkconfiguration.py +0 -7
  34. mistralai_azure/types/basemodel.py +3 -3
  35. mistralai_azure/utils/__init__.py +130 -45
  36. mistralai_azure/utils/datetimes.py +23 -0
  37. mistralai_azure/utils/enums.py +67 -27
  38. mistralai_azure/utils/forms.py +49 -28
  39. mistralai_azure/utils/serializers.py +32 -3
  40. {mistralai-1.9.7.dist-info → mistralai-1.9.9.dist-info}/LICENSE +0 -0
  41. {mistralai-1.9.7.dist-info → mistralai-1.9.9.dist-info}/WHEEL +0 -0
mistralai_azure/ocr.py ADDED
@@ -0,0 +1,271 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from .basesdk import BaseSDK
4
+ from mistralai_azure import models, utils
5
+ from mistralai_azure._hooks import HookContext
6
+ from mistralai_azure.types import Nullable, OptionalNullable, UNSET
7
+ from typing import Any, List, Mapping, Optional, Union
8
+
9
+
10
+ class Ocr(BaseSDK):
11
+ def process(
12
+ self,
13
+ *,
14
+ model: Nullable[str],
15
+ document: Union[models.Document, models.DocumentTypedDict],
16
+ id: Optional[str] = None,
17
+ pages: OptionalNullable[List[int]] = UNSET,
18
+ include_image_base64: OptionalNullable[bool] = UNSET,
19
+ image_limit: OptionalNullable[int] = UNSET,
20
+ image_min_size: OptionalNullable[int] = UNSET,
21
+ bbox_annotation_format: OptionalNullable[
22
+ Union[models.ResponseFormat, models.ResponseFormatTypedDict]
23
+ ] = UNSET,
24
+ document_annotation_format: OptionalNullable[
25
+ Union[models.ResponseFormat, models.ResponseFormatTypedDict]
26
+ ] = UNSET,
27
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
28
+ server_url: Optional[str] = None,
29
+ timeout_ms: Optional[int] = None,
30
+ http_headers: Optional[Mapping[str, str]] = None,
31
+ ) -> Optional[models.OCRResponse]:
32
+ r"""OCR
33
+
34
+ :param model:
35
+ :param document: Document to run OCR on
36
+ :param id:
37
+ :param pages: Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0
38
+ :param include_image_base64: Include image URLs in response
39
+ :param image_limit: Max images to extract
40
+ :param image_min_size: Minimum height and width of image to extract
41
+ :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field
42
+ :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field
43
+ :param retries: Override the default retry configuration for this method
44
+ :param server_url: Override the default server URL for this method
45
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
46
+ :param http_headers: Additional headers to set or replace on requests.
47
+ """
48
+ base_url = None
49
+ url_variables = None
50
+ if timeout_ms is None:
51
+ timeout_ms = self.sdk_configuration.timeout_ms
52
+
53
+ if server_url is not None:
54
+ base_url = server_url
55
+ else:
56
+ base_url = self._get_url(base_url, url_variables)
57
+
58
+ request = models.OCRRequest(
59
+ model=model,
60
+ id=id,
61
+ document=utils.get_pydantic_model(document, models.Document),
62
+ pages=pages,
63
+ include_image_base64=include_image_base64,
64
+ image_limit=image_limit,
65
+ image_min_size=image_min_size,
66
+ bbox_annotation_format=utils.get_pydantic_model(
67
+ bbox_annotation_format, OptionalNullable[models.ResponseFormat]
68
+ ),
69
+ document_annotation_format=utils.get_pydantic_model(
70
+ document_annotation_format, OptionalNullable[models.ResponseFormat]
71
+ ),
72
+ )
73
+
74
+ req = self._build_request(
75
+ method="POST",
76
+ path="/ocr",
77
+ base_url=base_url,
78
+ url_variables=url_variables,
79
+ request=request,
80
+ request_body_required=True,
81
+ request_has_path_params=False,
82
+ request_has_query_params=True,
83
+ user_agent_header="user-agent",
84
+ accept_header_value="application/json",
85
+ http_headers=http_headers,
86
+ security=self.sdk_configuration.security,
87
+ get_serialized_body=lambda: utils.serialize_request_body(
88
+ request, False, False, "json", models.OCRRequest
89
+ ),
90
+ timeout_ms=timeout_ms,
91
+ )
92
+
93
+ if retries == UNSET:
94
+ if self.sdk_configuration.retry_config is not UNSET:
95
+ retries = self.sdk_configuration.retry_config
96
+
97
+ retry_config = None
98
+ if isinstance(retries, utils.RetryConfig):
99
+ retry_config = (retries, ["429", "500", "502", "503", "504"])
100
+
101
+ http_res = self.do_request(
102
+ hook_ctx=HookContext(
103
+ config=self.sdk_configuration,
104
+ base_url=base_url or "",
105
+ operation_id="ocr_v1_ocr_post",
106
+ oauth2_scopes=[],
107
+ security_source=self.sdk_configuration.security,
108
+ ),
109
+ request=req,
110
+ error_status_codes=["422", "4XX", "5XX"],
111
+ retry_config=retry_config,
112
+ )
113
+
114
+ response_data: Any = None
115
+ if utils.match_response(http_res, "200", "application/json"):
116
+ return utils.unmarshal_json(http_res.text, Optional[models.OCRResponse])
117
+ if utils.match_response(http_res, "422", "application/json"):
118
+ response_data = utils.unmarshal_json(
119
+ http_res.text, models.HTTPValidationErrorData
120
+ )
121
+ raise models.HTTPValidationError(data=response_data)
122
+ if utils.match_response(http_res, "4XX", "*"):
123
+ http_res_text = utils.stream_to_text(http_res)
124
+ raise models.SDKError(
125
+ "API error occurred", http_res.status_code, http_res_text, http_res
126
+ )
127
+ if utils.match_response(http_res, "5XX", "*"):
128
+ http_res_text = utils.stream_to_text(http_res)
129
+ raise models.SDKError(
130
+ "API error occurred", http_res.status_code, http_res_text, http_res
131
+ )
132
+
133
+ content_type = http_res.headers.get("Content-Type")
134
+ http_res_text = utils.stream_to_text(http_res)
135
+ raise models.SDKError(
136
+ f"Unexpected response received (code: {http_res.status_code}, type: {content_type})",
137
+ http_res.status_code,
138
+ http_res_text,
139
+ http_res,
140
+ )
141
+
142
+ async def process_async(
143
+ self,
144
+ *,
145
+ model: Nullable[str],
146
+ document: Union[models.Document, models.DocumentTypedDict],
147
+ id: Optional[str] = None,
148
+ pages: OptionalNullable[List[int]] = UNSET,
149
+ include_image_base64: OptionalNullable[bool] = UNSET,
150
+ image_limit: OptionalNullable[int] = UNSET,
151
+ image_min_size: OptionalNullable[int] = UNSET,
152
+ bbox_annotation_format: OptionalNullable[
153
+ Union[models.ResponseFormat, models.ResponseFormatTypedDict]
154
+ ] = UNSET,
155
+ document_annotation_format: OptionalNullable[
156
+ Union[models.ResponseFormat, models.ResponseFormatTypedDict]
157
+ ] = UNSET,
158
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
159
+ server_url: Optional[str] = None,
160
+ timeout_ms: Optional[int] = None,
161
+ http_headers: Optional[Mapping[str, str]] = None,
162
+ ) -> Optional[models.OCRResponse]:
163
+ r"""OCR
164
+
165
+ :param model:
166
+ :param document: Document to run OCR on
167
+ :param id:
168
+ :param pages: Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0
169
+ :param include_image_base64: Include image URLs in response
170
+ :param image_limit: Max images to extract
171
+ :param image_min_size: Minimum height and width of image to extract
172
+ :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field
173
+ :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field
174
+ :param retries: Override the default retry configuration for this method
175
+ :param server_url: Override the default server URL for this method
176
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
177
+ :param http_headers: Additional headers to set or replace on requests.
178
+ """
179
+ base_url = None
180
+ url_variables = None
181
+ if timeout_ms is None:
182
+ timeout_ms = self.sdk_configuration.timeout_ms
183
+
184
+ if server_url is not None:
185
+ base_url = server_url
186
+ else:
187
+ base_url = self._get_url(base_url, url_variables)
188
+
189
+ request = models.OCRRequest(
190
+ model=model,
191
+ id=id,
192
+ document=utils.get_pydantic_model(document, models.Document),
193
+ pages=pages,
194
+ include_image_base64=include_image_base64,
195
+ image_limit=image_limit,
196
+ image_min_size=image_min_size,
197
+ bbox_annotation_format=utils.get_pydantic_model(
198
+ bbox_annotation_format, OptionalNullable[models.ResponseFormat]
199
+ ),
200
+ document_annotation_format=utils.get_pydantic_model(
201
+ document_annotation_format, OptionalNullable[models.ResponseFormat]
202
+ ),
203
+ )
204
+
205
+ req = self._build_request_async(
206
+ method="POST",
207
+ path="/ocr",
208
+ base_url=base_url,
209
+ url_variables=url_variables,
210
+ request=request,
211
+ request_body_required=True,
212
+ request_has_path_params=False,
213
+ request_has_query_params=True,
214
+ user_agent_header="user-agent",
215
+ accept_header_value="application/json",
216
+ http_headers=http_headers,
217
+ security=self.sdk_configuration.security,
218
+ get_serialized_body=lambda: utils.serialize_request_body(
219
+ request, False, False, "json", models.OCRRequest
220
+ ),
221
+ timeout_ms=timeout_ms,
222
+ )
223
+
224
+ if retries == UNSET:
225
+ if self.sdk_configuration.retry_config is not UNSET:
226
+ retries = self.sdk_configuration.retry_config
227
+
228
+ retry_config = None
229
+ if isinstance(retries, utils.RetryConfig):
230
+ retry_config = (retries, ["429", "500", "502", "503", "504"])
231
+
232
+ http_res = await self.do_request_async(
233
+ hook_ctx=HookContext(
234
+ config=self.sdk_configuration,
235
+ base_url=base_url or "",
236
+ operation_id="ocr_v1_ocr_post",
237
+ oauth2_scopes=[],
238
+ security_source=self.sdk_configuration.security,
239
+ ),
240
+ request=req,
241
+ error_status_codes=["422", "4XX", "5XX"],
242
+ retry_config=retry_config,
243
+ )
244
+
245
+ response_data: Any = None
246
+ if utils.match_response(http_res, "200", "application/json"):
247
+ return utils.unmarshal_json(http_res.text, Optional[models.OCRResponse])
248
+ if utils.match_response(http_res, "422", "application/json"):
249
+ response_data = utils.unmarshal_json(
250
+ http_res.text, models.HTTPValidationErrorData
251
+ )
252
+ raise models.HTTPValidationError(data=response_data)
253
+ if utils.match_response(http_res, "4XX", "*"):
254
+ http_res_text = await utils.stream_to_text_async(http_res)
255
+ raise models.SDKError(
256
+ "API error occurred", http_res.status_code, http_res_text, http_res
257
+ )
258
+ if utils.match_response(http_res, "5XX", "*"):
259
+ http_res_text = await utils.stream_to_text_async(http_res)
260
+ raise models.SDKError(
261
+ "API error occurred", http_res.status_code, http_res_text, http_res
262
+ )
263
+
264
+ content_type = http_res.headers.get("Content-Type")
265
+ http_res_text = await utils.stream_to_text_async(http_res)
266
+ raise models.SDKError(
267
+ f"Unexpected response received (code: {http_res.status_code}, type: {content_type})",
268
+ http_res.status_code,
269
+ http_res_text,
270
+ http_res,
271
+ )
mistralai_azure/sdk.py CHANGED
@@ -1,27 +1,33 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
- import weakref
4
- from typing import Any, Callable, Dict, Optional, Union, cast
5
-
6
- import httpx
7
-
8
- from mistralai_azure import models, utils
9
- from mistralai_azure._hooks import SDKHooks
10
- from mistralai_azure.chat import Chat
11
- from mistralai_azure.types import UNSET, OptionalNullable
12
-
13
3
  from .basesdk import BaseSDK
14
4
  from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
15
5
  from .sdkconfiguration import SDKConfiguration
16
6
  from .utils.logger import Logger, get_default_logger
17
7
  from .utils.retries import RetryConfig
8
+ import httpx
9
+ import importlib
10
+ from mistralai_azure import models, utils
11
+ from mistralai_azure._hooks import SDKHooks
12
+ from mistralai_azure.types import OptionalNullable, UNSET
13
+ from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union, cast
14
+ import weakref
15
+
16
+ if TYPE_CHECKING:
17
+ from mistralai_azure.chat import Chat
18
+ from mistralai_azure.ocr import Ocr
18
19
 
19
20
 
20
21
  class MistralAzure(BaseSDK):
21
22
  r"""Mistral AI API: Our Chat Completion and Embeddings APIs specification. Create your account on [La Plateforme](https://console.mistral.ai) to get access and read the [docs](https://docs.mistral.ai) to learn how to use it."""
22
23
 
23
- chat: Chat
24
+ chat: "Chat"
24
25
  r"""Chat Completion API."""
26
+ ocr: "Ocr"
27
+ _sub_sdk_map = {
28
+ "chat": ("mistralai_azure.chat", "Chat"),
29
+ "ocr": ("mistralai_azure.ocr", "Ocr"),
30
+ }
25
31
 
26
32
  def __init__(
27
33
  self,
@@ -101,6 +107,9 @@ class MistralAzure(BaseSDK):
101
107
 
102
108
  hooks = SDKHooks()
103
109
 
110
+ # pylint: disable=protected-access
111
+ self.sdk_configuration.__dict__["_hooks"] = hooks
112
+
104
113
  current_server_url, *_ = self.sdk_configuration.get_server_details()
105
114
  server_url, self.sdk_configuration.client = hooks.sdk_init(
106
115
  current_server_url, client
@@ -108,9 +117,6 @@ class MistralAzure(BaseSDK):
108
117
  if current_server_url != server_url:
109
118
  self.sdk_configuration.server_url = server_url
110
119
 
111
- # pylint: disable=protected-access
112
- self.sdk_configuration.__dict__["_hooks"] = hooks
113
-
114
120
  weakref.finalize(
115
121
  self,
116
122
  close_clients,
@@ -121,10 +127,32 @@ class MistralAzure(BaseSDK):
121
127
  self.sdk_configuration.async_client_supplied,
122
128
  )
123
129
 
124
- self._init_sdks()
130
+ def __getattr__(self, name: str):
131
+ if name in self._sub_sdk_map:
132
+ module_path, class_name = self._sub_sdk_map[name]
133
+ try:
134
+ module = importlib.import_module(module_path)
135
+ klass = getattr(module, class_name)
136
+ instance = klass(self.sdk_configuration)
137
+ setattr(self, name, instance)
138
+ return instance
139
+ except ImportError as e:
140
+ raise AttributeError(
141
+ f"Failed to import module {module_path} for attribute {name}: {e}"
142
+ ) from e
143
+ except AttributeError as e:
144
+ raise AttributeError(
145
+ f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
146
+ ) from e
147
+
148
+ raise AttributeError(
149
+ f"'{type(self).__name__}' object has no attribute '{name}'"
150
+ )
125
151
 
126
- def _init_sdks(self):
127
- self.chat = Chat(self.sdk_configuration)
152
+ def __dir__(self):
153
+ default_attrs = list(super().__dir__())
154
+ lazy_attrs = list(self._sub_sdk_map.keys())
155
+ return sorted(list(set(default_attrs + lazy_attrs)))
128
156
 
129
157
  def __enter__(self):
130
158
  return self
@@ -1,6 +1,5 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
- from ._hooks import SDKHooks
4
3
  from ._version import (
5
4
  __gen_version__,
6
5
  __openapi_doc_version__,
@@ -42,9 +41,6 @@ class SDKConfiguration:
42
41
  retry_config: OptionalNullable[RetryConfig] = Field(default_factory=lambda: UNSET)
43
42
  timeout_ms: Optional[int] = None
44
43
 
45
- def __post_init__(self):
46
- self._hooks = SDKHooks()
47
-
48
44
  def get_server_details(self) -> Tuple[str, Dict[str, str]]:
49
45
  if self.server_url is not None and self.server_url:
50
46
  return remove_suffix(self.server_url, "/"), {}
@@ -55,6 +51,3 @@ class SDKConfiguration:
55
51
  raise ValueError(f'Invalid server "{self.server}"')
56
52
 
57
53
  return SERVERS[self.server], {}
58
-
59
- def get_hooks(self) -> SDKHooks:
60
- return self._hooks
@@ -2,7 +2,7 @@
2
2
 
3
3
  from pydantic import ConfigDict, model_serializer
4
4
  from pydantic import BaseModel as PydanticBaseModel
5
- from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union, NewType
5
+ from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union
6
6
  from typing_extensions import TypeAliasType, TypeAlias
7
7
 
8
8
 
@@ -35,5 +35,5 @@ else:
35
35
  "OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
36
36
  )
37
37
 
38
- UnrecognizedInt = NewType("UnrecognizedInt", int)
39
- UnrecognizedStr = NewType("UnrecognizedStr", str)
38
+ UnrecognizedInt: TypeAlias = int
39
+ UnrecognizedStr: TypeAlias = str
@@ -1,50 +1,55 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
- from .annotations import get_discriminator
4
- from .enums import OpenEnumMeta
5
- from .headers import get_headers, get_response_headers
6
- from .metadata import (
7
- FieldMetadata,
8
- find_metadata,
9
- FormMetadata,
10
- HeaderMetadata,
11
- MultipartFormMetadata,
12
- PathParamMetadata,
13
- QueryParamMetadata,
14
- RequestMetadata,
15
- SecurityMetadata,
16
- )
17
- from .queryparams import get_query_params
18
- from .retries import BackoffStrategy, Retries, retry, retry_async, RetryConfig
19
- from .requestbodies import serialize_request_body, SerializedRequestBody
20
- from .security import get_security
21
- from .serializers import (
22
- get_pydantic_model,
23
- marshal_json,
24
- unmarshal,
25
- unmarshal_json,
26
- serialize_decimal,
27
- serialize_float,
28
- serialize_int,
29
- stream_to_text,
30
- stream_to_text_async,
31
- stream_to_bytes,
32
- stream_to_bytes_async,
33
- validate_const,
34
- validate_decimal,
35
- validate_float,
36
- validate_int,
37
- validate_open_enum,
38
- )
39
- from .url import generate_url, template_url, remove_suffix
40
- from .values import (
41
- get_global_from_env,
42
- match_content_type,
43
- match_status_codes,
44
- match_response,
45
- cast_partial,
46
- )
47
- from .logger import Logger, get_body_content, get_default_logger
3
+ from typing import TYPE_CHECKING
4
+ from importlib import import_module
5
+
6
+ if TYPE_CHECKING:
7
+ from .annotations import get_discriminator
8
+ from .datetimes import parse_datetime
9
+ from .enums import OpenEnumMeta
10
+ from .headers import get_headers, get_response_headers
11
+ from .metadata import (
12
+ FieldMetadata,
13
+ find_metadata,
14
+ FormMetadata,
15
+ HeaderMetadata,
16
+ MultipartFormMetadata,
17
+ PathParamMetadata,
18
+ QueryParamMetadata,
19
+ RequestMetadata,
20
+ SecurityMetadata,
21
+ )
22
+ from .queryparams import get_query_params
23
+ from .retries import BackoffStrategy, Retries, retry, retry_async, RetryConfig
24
+ from .requestbodies import serialize_request_body, SerializedRequestBody
25
+ from .security import get_security
26
+ from .serializers import (
27
+ get_pydantic_model,
28
+ marshal_json,
29
+ unmarshal,
30
+ unmarshal_json,
31
+ serialize_decimal,
32
+ serialize_float,
33
+ serialize_int,
34
+ stream_to_text,
35
+ stream_to_text_async,
36
+ stream_to_bytes,
37
+ stream_to_bytes_async,
38
+ validate_const,
39
+ validate_decimal,
40
+ validate_float,
41
+ validate_int,
42
+ validate_open_enum,
43
+ )
44
+ from .url import generate_url, template_url, remove_suffix
45
+ from .values import (
46
+ get_global_from_env,
47
+ match_content_type,
48
+ match_status_codes,
49
+ match_response,
50
+ cast_partial,
51
+ )
52
+ from .logger import Logger, get_body_content, get_default_logger
48
53
 
49
54
  __all__ = [
50
55
  "BackoffStrategy",
@@ -55,6 +60,7 @@ __all__ = [
55
60
  "get_body_content",
56
61
  "get_default_logger",
57
62
  "get_discriminator",
63
+ "parse_datetime",
58
64
  "get_global_from_env",
59
65
  "get_headers",
60
66
  "get_pydantic_model",
@@ -97,3 +103,82 @@ __all__ = [
97
103
  "validate_open_enum",
98
104
  "cast_partial",
99
105
  ]
106
+
107
+ _dynamic_imports: dict[str, str] = {
108
+ "BackoffStrategy": ".retries",
109
+ "FieldMetadata": ".metadata",
110
+ "find_metadata": ".metadata",
111
+ "FormMetadata": ".metadata",
112
+ "generate_url": ".url",
113
+ "get_body_content": ".logger",
114
+ "get_default_logger": ".logger",
115
+ "get_discriminator": ".annotations",
116
+ "parse_datetime": ".datetimes",
117
+ "get_global_from_env": ".values",
118
+ "get_headers": ".headers",
119
+ "get_pydantic_model": ".serializers",
120
+ "get_query_params": ".queryparams",
121
+ "get_response_headers": ".headers",
122
+ "get_security": ".security",
123
+ "HeaderMetadata": ".metadata",
124
+ "Logger": ".logger",
125
+ "marshal_json": ".serializers",
126
+ "match_content_type": ".values",
127
+ "match_status_codes": ".values",
128
+ "match_response": ".values",
129
+ "MultipartFormMetadata": ".metadata",
130
+ "OpenEnumMeta": ".enums",
131
+ "PathParamMetadata": ".metadata",
132
+ "QueryParamMetadata": ".metadata",
133
+ "remove_suffix": ".url",
134
+ "Retries": ".retries",
135
+ "retry": ".retries",
136
+ "retry_async": ".retries",
137
+ "RetryConfig": ".retries",
138
+ "RequestMetadata": ".metadata",
139
+ "SecurityMetadata": ".metadata",
140
+ "serialize_decimal": ".serializers",
141
+ "serialize_float": ".serializers",
142
+ "serialize_int": ".serializers",
143
+ "serialize_request_body": ".requestbodies",
144
+ "SerializedRequestBody": ".requestbodies",
145
+ "stream_to_text": ".serializers",
146
+ "stream_to_text_async": ".serializers",
147
+ "stream_to_bytes": ".serializers",
148
+ "stream_to_bytes_async": ".serializers",
149
+ "template_url": ".url",
150
+ "unmarshal": ".serializers",
151
+ "unmarshal_json": ".serializers",
152
+ "validate_decimal": ".serializers",
153
+ "validate_const": ".serializers",
154
+ "validate_float": ".serializers",
155
+ "validate_int": ".serializers",
156
+ "validate_open_enum": ".serializers",
157
+ "cast_partial": ".values",
158
+ }
159
+
160
+
161
+ def __getattr__(attr_name: str) -> object:
162
+ module_name = _dynamic_imports.get(attr_name)
163
+ if module_name is None:
164
+ raise AttributeError(
165
+ f"no {attr_name} found in _dynamic_imports, module name -> {__name__} "
166
+ )
167
+
168
+ try:
169
+ module = import_module(module_name, __package__)
170
+ result = getattr(module, attr_name)
171
+ return result
172
+ except ImportError as e:
173
+ raise ImportError(
174
+ f"Failed to import {attr_name} from {module_name}: {e}"
175
+ ) from e
176
+ except AttributeError as e:
177
+ raise AttributeError(
178
+ f"Failed to get {attr_name} from {module_name}: {e}"
179
+ ) from e
180
+
181
+
182
+ def __dir__():
183
+ lazy_attrs = list(_dynamic_imports.keys())
184
+ return sorted(lazy_attrs)
@@ -0,0 +1,23 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from datetime import datetime
4
+ import sys
5
+
6
+
7
+ def parse_datetime(datetime_string: str) -> datetime:
8
+ """
9
+ Convert a RFC 3339 / ISO 8601 formatted string into a datetime object.
10
+ Python versions 3.11 and later support parsing RFC 3339 directly with
11
+ datetime.fromisoformat(), but for earlier versions, this function
12
+ encapsulates the necessary extra logic.
13
+ """
14
+ # Python 3.11 and later can parse RFC 3339 directly
15
+ if sys.version_info >= (3, 11):
16
+ return datetime.fromisoformat(datetime_string)
17
+
18
+ # For Python 3.10 and earlier, a common ValueError is trailing 'Z' suffix,
19
+ # so fix that upfront.
20
+ if datetime_string.endswith("Z"):
21
+ datetime_string = datetime_string[:-1] + "+00:00"
22
+
23
+ return datetime.fromisoformat(datetime_string)