train-travel 0.0.7__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.
- train_travel/__init__.py +17 -0
- train_travel/_hooks/__init__.py +6 -0
- train_travel/_hooks/oauth2scopes.py +16 -0
- train_travel/_hooks/registration.py +13 -0
- train_travel/_hooks/sdkhooks.py +76 -0
- train_travel/_hooks/types.py +112 -0
- train_travel/_version.py +15 -0
- train_travel/basesdk.py +388 -0
- train_travel/bookings.py +1190 -0
- train_travel/errors/__init__.py +63 -0
- train_travel/errors/no_response_error.py +17 -0
- train_travel/errors/responsevalidationerror.py +27 -0
- train_travel/errors/traintraveldefaulterror.py +40 -0
- train_travel/errors/traintravelerror.py +30 -0
- train_travel/httpclient.py +125 -0
- train_travel/models/__init__.py +416 -0
- train_travel/models/booking.py +59 -0
- train_travel/models/booking_input.py +52 -0
- train_travel/models/bookingpayment.py +221 -0
- train_travel/models/create_booking_paymentop.py +269 -0
- train_travel/models/create_booking_rawop.py +144 -0
- train_travel/models/create_bookingop.py +144 -0
- train_travel/models/delete_bookingop.py +30 -0
- train_travel/models/get_bookingop.py +159 -0
- train_travel/models/get_bookingsop.py +198 -0
- train_travel/models/get_stationsop.py +230 -0
- train_travel/models/get_tripsop.py +324 -0
- train_travel/models/links_booking.py +35 -0
- train_travel/models/links_self.py +36 -0
- train_travel/models/new_bookingop.py +92 -0
- train_travel/models/security.py +39 -0
- train_travel/models/station.py +57 -0
- train_travel/models/trip.py +90 -0
- train_travel/payments.py +262 -0
- train_travel/py.typed +1 -0
- train_travel/sdk.py +213 -0
- train_travel/sdkconfiguration.py +51 -0
- train_travel/stations.py +284 -0
- train_travel/trips.py +291 -0
- train_travel/types/__init__.py +21 -0
- train_travel/types/basemodel.py +77 -0
- train_travel/utils/__init__.py +206 -0
- train_travel/utils/annotations.py +79 -0
- train_travel/utils/datetimes.py +23 -0
- train_travel/utils/enums.py +134 -0
- train_travel/utils/eventstreaming.py +248 -0
- train_travel/utils/forms.py +234 -0
- train_travel/utils/headers.py +136 -0
- train_travel/utils/logger.py +27 -0
- train_travel/utils/metadata.py +118 -0
- train_travel/utils/queryparams.py +217 -0
- train_travel/utils/requestbodies.py +66 -0
- train_travel/utils/retries.py +281 -0
- train_travel/utils/security.py +192 -0
- train_travel/utils/serializers.py +229 -0
- train_travel/utils/unmarshal_json_response.py +38 -0
- train_travel/utils/url.py +155 -0
- train_travel/utils/values.py +137 -0
- train_travel-0.0.7.dist-info/METADATA +567 -0
- train_travel-0.0.7.dist-info/RECORD +62 -0
- train_travel-0.0.7.dist-info/WHEEL +5 -0
- train_travel-0.0.7.dist-info/top_level.txt +1 -0
train_travel/trips.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from .basesdk import BaseSDK
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from train_travel import errors, models, utils
|
|
7
|
+
from train_travel._hooks import HookContext
|
|
8
|
+
from train_travel.types import OptionalNullable, UNSET
|
|
9
|
+
from train_travel.utils import get_security_from_env
|
|
10
|
+
from train_travel.utils.unmarshal_json_response import unmarshal_json_response
|
|
11
|
+
from typing import Mapping, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GetTripsAcceptEnum(str, Enum):
|
|
15
|
+
APPLICATION_JSON = "application/json"
|
|
16
|
+
APPLICATION_XML = "application/xml"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Trips(BaseSDK):
|
|
20
|
+
r"""Timetables and routes for train trips between stations, including pricing
|
|
21
|
+
and availability.
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def get_trips(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
origin: str,
|
|
29
|
+
destination: str,
|
|
30
|
+
date_: datetime,
|
|
31
|
+
page: Optional[int] = 1,
|
|
32
|
+
limit: Optional[int] = 10,
|
|
33
|
+
bicycles: Optional[bool] = False,
|
|
34
|
+
dogs: Optional[bool] = False,
|
|
35
|
+
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
|
36
|
+
server_url: Optional[str] = None,
|
|
37
|
+
timeout_ms: Optional[int] = None,
|
|
38
|
+
accept_header_override: Optional[GetTripsAcceptEnum] = None,
|
|
39
|
+
http_headers: Optional[Mapping[str, str]] = None,
|
|
40
|
+
) -> models.GetTripsResponse:
|
|
41
|
+
r"""Get available train trips
|
|
42
|
+
|
|
43
|
+
Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
:param origin: The ID of the origin station
|
|
47
|
+
:param destination: The ID of the destination station
|
|
48
|
+
:param date_: The date and time of the trip in ISO 8601 format in origin station's timezone.
|
|
49
|
+
:param page: The page number to return
|
|
50
|
+
:param limit: The number of items to return per page
|
|
51
|
+
:param bicycles: Only return trips where bicycles are known to be allowed
|
|
52
|
+
:param dogs: Only return trips where dogs are known to be allowed
|
|
53
|
+
:param retries: Override the default retry configuration for this method
|
|
54
|
+
:param server_url: Override the default server URL for this method
|
|
55
|
+
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
|
56
|
+
:param accept_header_override: Override the default accept header for this method
|
|
57
|
+
:param http_headers: Additional headers to set or replace on requests.
|
|
58
|
+
"""
|
|
59
|
+
base_url = None
|
|
60
|
+
url_variables = None
|
|
61
|
+
if timeout_ms is None:
|
|
62
|
+
timeout_ms = self.sdk_configuration.timeout_ms
|
|
63
|
+
|
|
64
|
+
if server_url is not None:
|
|
65
|
+
base_url = server_url
|
|
66
|
+
else:
|
|
67
|
+
base_url = self._get_url(base_url, url_variables)
|
|
68
|
+
|
|
69
|
+
request = models.GetTripsRequest(
|
|
70
|
+
page=page,
|
|
71
|
+
limit=limit,
|
|
72
|
+
origin=origin,
|
|
73
|
+
destination=destination,
|
|
74
|
+
date_=date_,
|
|
75
|
+
bicycles=bicycles,
|
|
76
|
+
dogs=dogs,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
req = self._build_request(
|
|
80
|
+
method="GET",
|
|
81
|
+
path="/trips",
|
|
82
|
+
base_url=base_url,
|
|
83
|
+
url_variables=url_variables,
|
|
84
|
+
request=request,
|
|
85
|
+
request_body_required=False,
|
|
86
|
+
request_has_path_params=False,
|
|
87
|
+
request_has_query_params=True,
|
|
88
|
+
user_agent_header="user-agent",
|
|
89
|
+
accept_header_value=accept_header_override.value
|
|
90
|
+
if accept_header_override is not None
|
|
91
|
+
else "application/json;q=1, application/xml;q=0",
|
|
92
|
+
http_headers=http_headers,
|
|
93
|
+
security=self.sdk_configuration.security,
|
|
94
|
+
allow_empty_value=None,
|
|
95
|
+
timeout_ms=timeout_ms,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if retries == UNSET:
|
|
99
|
+
if self.sdk_configuration.retry_config is not UNSET:
|
|
100
|
+
retries = self.sdk_configuration.retry_config
|
|
101
|
+
else:
|
|
102
|
+
retries = utils.RetryConfig(
|
|
103
|
+
"backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
retry_config = None
|
|
107
|
+
if isinstance(retries, utils.RetryConfig):
|
|
108
|
+
retry_config = (retries, ["5XX"])
|
|
109
|
+
|
|
110
|
+
http_res = self.do_request(
|
|
111
|
+
hook_ctx=HookContext(
|
|
112
|
+
config=self.sdk_configuration,
|
|
113
|
+
base_url=base_url or "",
|
|
114
|
+
operation_id="get-trips",
|
|
115
|
+
oauth2_scopes=None,
|
|
116
|
+
security_source=get_security_from_env(
|
|
117
|
+
self.sdk_configuration.security, models.Security
|
|
118
|
+
),
|
|
119
|
+
),
|
|
120
|
+
request=req,
|
|
121
|
+
error_status_codes=["400", "401", "403", "429", "4XX", "500", "5XX"],
|
|
122
|
+
retry_config=retry_config,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if utils.match_response(http_res, "200", "application/json"):
|
|
126
|
+
return models.GetTripsResponse(
|
|
127
|
+
result=unmarshal_json_response(models.GetTripsResponseBody, http_res),
|
|
128
|
+
headers=utils.get_response_headers(http_res.headers),
|
|
129
|
+
)
|
|
130
|
+
if utils.match_response(http_res, "200", "application/xml"):
|
|
131
|
+
http_res_bytes = utils.stream_to_bytes(http_res)
|
|
132
|
+
return models.GetTripsResponse(
|
|
133
|
+
result=http_res_bytes,
|
|
134
|
+
headers=utils.get_response_headers(http_res.headers),
|
|
135
|
+
)
|
|
136
|
+
if utils.match_response(http_res, ["400", "401", "403", "429"], "*"):
|
|
137
|
+
http_res_text = utils.stream_to_text(http_res)
|
|
138
|
+
raise errors.TrainTravelDefaultError(
|
|
139
|
+
"API error occurred", http_res, http_res_text
|
|
140
|
+
)
|
|
141
|
+
if utils.match_response(http_res, "500", "*"):
|
|
142
|
+
http_res_text = utils.stream_to_text(http_res)
|
|
143
|
+
raise errors.TrainTravelDefaultError(
|
|
144
|
+
"API error occurred", http_res, http_res_text
|
|
145
|
+
)
|
|
146
|
+
if utils.match_response(http_res, "4XX", "*"):
|
|
147
|
+
http_res_text = utils.stream_to_text(http_res)
|
|
148
|
+
raise errors.TrainTravelDefaultError(
|
|
149
|
+
"API error occurred", http_res, http_res_text
|
|
150
|
+
)
|
|
151
|
+
if utils.match_response(http_res, "5XX", "*"):
|
|
152
|
+
http_res_text = utils.stream_to_text(http_res)
|
|
153
|
+
raise errors.TrainTravelDefaultError(
|
|
154
|
+
"API error occurred", http_res, http_res_text
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
raise errors.TrainTravelDefaultError("Unexpected response received", http_res)
|
|
158
|
+
|
|
159
|
+
async def get_trips_async(
|
|
160
|
+
self,
|
|
161
|
+
*,
|
|
162
|
+
origin: str,
|
|
163
|
+
destination: str,
|
|
164
|
+
date_: datetime,
|
|
165
|
+
page: Optional[int] = 1,
|
|
166
|
+
limit: Optional[int] = 10,
|
|
167
|
+
bicycles: Optional[bool] = False,
|
|
168
|
+
dogs: Optional[bool] = False,
|
|
169
|
+
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
|
170
|
+
server_url: Optional[str] = None,
|
|
171
|
+
timeout_ms: Optional[int] = None,
|
|
172
|
+
accept_header_override: Optional[GetTripsAcceptEnum] = None,
|
|
173
|
+
http_headers: Optional[Mapping[str, str]] = None,
|
|
174
|
+
) -> models.GetTripsResponse:
|
|
175
|
+
r"""Get available train trips
|
|
176
|
+
|
|
177
|
+
Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
:param origin: The ID of the origin station
|
|
181
|
+
:param destination: The ID of the destination station
|
|
182
|
+
:param date_: The date and time of the trip in ISO 8601 format in origin station's timezone.
|
|
183
|
+
:param page: The page number to return
|
|
184
|
+
:param limit: The number of items to return per page
|
|
185
|
+
:param bicycles: Only return trips where bicycles are known to be allowed
|
|
186
|
+
:param dogs: Only return trips where dogs are known to be allowed
|
|
187
|
+
:param retries: Override the default retry configuration for this method
|
|
188
|
+
:param server_url: Override the default server URL for this method
|
|
189
|
+
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
|
190
|
+
:param accept_header_override: Override the default accept header for this method
|
|
191
|
+
:param http_headers: Additional headers to set or replace on requests.
|
|
192
|
+
"""
|
|
193
|
+
base_url = None
|
|
194
|
+
url_variables = None
|
|
195
|
+
if timeout_ms is None:
|
|
196
|
+
timeout_ms = self.sdk_configuration.timeout_ms
|
|
197
|
+
|
|
198
|
+
if server_url is not None:
|
|
199
|
+
base_url = server_url
|
|
200
|
+
else:
|
|
201
|
+
base_url = self._get_url(base_url, url_variables)
|
|
202
|
+
|
|
203
|
+
request = models.GetTripsRequest(
|
|
204
|
+
page=page,
|
|
205
|
+
limit=limit,
|
|
206
|
+
origin=origin,
|
|
207
|
+
destination=destination,
|
|
208
|
+
date_=date_,
|
|
209
|
+
bicycles=bicycles,
|
|
210
|
+
dogs=dogs,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
req = self._build_request_async(
|
|
214
|
+
method="GET",
|
|
215
|
+
path="/trips",
|
|
216
|
+
base_url=base_url,
|
|
217
|
+
url_variables=url_variables,
|
|
218
|
+
request=request,
|
|
219
|
+
request_body_required=False,
|
|
220
|
+
request_has_path_params=False,
|
|
221
|
+
request_has_query_params=True,
|
|
222
|
+
user_agent_header="user-agent",
|
|
223
|
+
accept_header_value=accept_header_override.value
|
|
224
|
+
if accept_header_override is not None
|
|
225
|
+
else "application/json;q=1, application/xml;q=0",
|
|
226
|
+
http_headers=http_headers,
|
|
227
|
+
security=self.sdk_configuration.security,
|
|
228
|
+
allow_empty_value=None,
|
|
229
|
+
timeout_ms=timeout_ms,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
if retries == UNSET:
|
|
233
|
+
if self.sdk_configuration.retry_config is not UNSET:
|
|
234
|
+
retries = self.sdk_configuration.retry_config
|
|
235
|
+
else:
|
|
236
|
+
retries = utils.RetryConfig(
|
|
237
|
+
"backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
retry_config = None
|
|
241
|
+
if isinstance(retries, utils.RetryConfig):
|
|
242
|
+
retry_config = (retries, ["5XX"])
|
|
243
|
+
|
|
244
|
+
http_res = await self.do_request_async(
|
|
245
|
+
hook_ctx=HookContext(
|
|
246
|
+
config=self.sdk_configuration,
|
|
247
|
+
base_url=base_url or "",
|
|
248
|
+
operation_id="get-trips",
|
|
249
|
+
oauth2_scopes=None,
|
|
250
|
+
security_source=get_security_from_env(
|
|
251
|
+
self.sdk_configuration.security, models.Security
|
|
252
|
+
),
|
|
253
|
+
),
|
|
254
|
+
request=req,
|
|
255
|
+
error_status_codes=["400", "401", "403", "429", "4XX", "500", "5XX"],
|
|
256
|
+
retry_config=retry_config,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if utils.match_response(http_res, "200", "application/json"):
|
|
260
|
+
return models.GetTripsResponse(
|
|
261
|
+
result=unmarshal_json_response(models.GetTripsResponseBody, http_res),
|
|
262
|
+
headers=utils.get_response_headers(http_res.headers),
|
|
263
|
+
)
|
|
264
|
+
if utils.match_response(http_res, "200", "application/xml"):
|
|
265
|
+
http_res_bytes = await utils.stream_to_bytes_async(http_res)
|
|
266
|
+
return models.GetTripsResponse(
|
|
267
|
+
result=http_res_bytes,
|
|
268
|
+
headers=utils.get_response_headers(http_res.headers),
|
|
269
|
+
)
|
|
270
|
+
if utils.match_response(http_res, ["400", "401", "403", "429"], "*"):
|
|
271
|
+
http_res_text = await utils.stream_to_text_async(http_res)
|
|
272
|
+
raise errors.TrainTravelDefaultError(
|
|
273
|
+
"API error occurred", http_res, http_res_text
|
|
274
|
+
)
|
|
275
|
+
if utils.match_response(http_res, "500", "*"):
|
|
276
|
+
http_res_text = await utils.stream_to_text_async(http_res)
|
|
277
|
+
raise errors.TrainTravelDefaultError(
|
|
278
|
+
"API error occurred", http_res, http_res_text
|
|
279
|
+
)
|
|
280
|
+
if utils.match_response(http_res, "4XX", "*"):
|
|
281
|
+
http_res_text = await utils.stream_to_text_async(http_res)
|
|
282
|
+
raise errors.TrainTravelDefaultError(
|
|
283
|
+
"API error occurred", http_res, http_res_text
|
|
284
|
+
)
|
|
285
|
+
if utils.match_response(http_res, "5XX", "*"):
|
|
286
|
+
http_res_text = await utils.stream_to_text_async(http_res)
|
|
287
|
+
raise errors.TrainTravelDefaultError(
|
|
288
|
+
"API error occurred", http_res, http_res_text
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
raise errors.TrainTravelDefaultError("Unexpected response received", http_res)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from .basemodel import (
|
|
4
|
+
BaseModel,
|
|
5
|
+
Nullable,
|
|
6
|
+
OptionalNullable,
|
|
7
|
+
UnrecognizedInt,
|
|
8
|
+
UnrecognizedStr,
|
|
9
|
+
UNSET,
|
|
10
|
+
UNSET_SENTINEL,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"BaseModel",
|
|
15
|
+
"Nullable",
|
|
16
|
+
"OptionalNullable",
|
|
17
|
+
"UnrecognizedInt",
|
|
18
|
+
"UnrecognizedStr",
|
|
19
|
+
"UNSET",
|
|
20
|
+
"UNSET_SENTINEL",
|
|
21
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from pydantic import ConfigDict, model_serializer
|
|
4
|
+
from pydantic import BaseModel as PydanticBaseModel
|
|
5
|
+
from pydantic_core import core_schema
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
|
|
7
|
+
from typing_extensions import TypeAliasType, TypeAlias
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseModel(PydanticBaseModel):
|
|
11
|
+
model_config = ConfigDict(
|
|
12
|
+
populate_by_name=True, arbitrary_types_allowed=True, protected_namespaces=()
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Unset(BaseModel):
|
|
17
|
+
@model_serializer(mode="plain")
|
|
18
|
+
def serialize_model(self):
|
|
19
|
+
return UNSET_SENTINEL
|
|
20
|
+
|
|
21
|
+
def __bool__(self) -> Literal[False]:
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
UNSET = Unset()
|
|
26
|
+
UNSET_SENTINEL = "~?~unset~?~sentinel~?~"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
T = TypeVar("T")
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
Nullable: TypeAlias = Union[T, None]
|
|
32
|
+
OptionalNullable: TypeAlias = Union[Optional[Nullable[T]], Unset]
|
|
33
|
+
else:
|
|
34
|
+
Nullable = TypeAliasType("Nullable", Union[T, None], type_params=(T,))
|
|
35
|
+
OptionalNullable = TypeAliasType(
|
|
36
|
+
"OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class UnrecognizedStr(str):
|
|
41
|
+
@classmethod
|
|
42
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
43
|
+
# Make UnrecognizedStr only work in lax mode, not strict mode
|
|
44
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
45
|
+
def validate_lax(v: Any) -> 'UnrecognizedStr':
|
|
46
|
+
if isinstance(v, cls):
|
|
47
|
+
return v
|
|
48
|
+
return cls(str(v))
|
|
49
|
+
|
|
50
|
+
# Use lax_or_strict_schema where strict always fails
|
|
51
|
+
# This forces Pydantic to prefer other union members in strict mode
|
|
52
|
+
# and only fall back to UnrecognizedStr in lax mode
|
|
53
|
+
return core_schema.lax_or_strict_schema(
|
|
54
|
+
lax_schema=core_schema.chain_schema([
|
|
55
|
+
core_schema.str_schema(),
|
|
56
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
57
|
+
]),
|
|
58
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class UnrecognizedInt(int):
|
|
63
|
+
@classmethod
|
|
64
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
65
|
+
# Make UnrecognizedInt only work in lax mode, not strict mode
|
|
66
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
67
|
+
def validate_lax(v: Any) -> 'UnrecognizedInt':
|
|
68
|
+
if isinstance(v, cls):
|
|
69
|
+
return v
|
|
70
|
+
return cls(int(v))
|
|
71
|
+
return core_schema.lax_or_strict_schema(
|
|
72
|
+
lax_schema=core_schema.chain_schema([
|
|
73
|
+
core_schema.int_schema(),
|
|
74
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
75
|
+
]),
|
|
76
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
77
|
+
)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Callable, TypeVar
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
import asyncio
|
|
6
|
+
import builtins
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
_T = TypeVar("_T")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def run_sync_in_thread(func: Callable[..., _T], *args) -> _T:
|
|
13
|
+
"""Run a synchronous function in a thread pool to avoid blocking the event loop."""
|
|
14
|
+
return await asyncio.to_thread(func, *args)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .annotations import get_discriminator
|
|
19
|
+
from .datetimes import parse_datetime
|
|
20
|
+
from .enums import OpenEnumMeta
|
|
21
|
+
from .headers import get_headers, get_response_headers
|
|
22
|
+
from .metadata import (
|
|
23
|
+
FieldMetadata,
|
|
24
|
+
find_metadata,
|
|
25
|
+
FormMetadata,
|
|
26
|
+
HeaderMetadata,
|
|
27
|
+
MultipartFormMetadata,
|
|
28
|
+
PathParamMetadata,
|
|
29
|
+
QueryParamMetadata,
|
|
30
|
+
RequestMetadata,
|
|
31
|
+
SecurityMetadata,
|
|
32
|
+
)
|
|
33
|
+
from .queryparams import get_query_params
|
|
34
|
+
from .retries import BackoffStrategy, Retries, retry, retry_async, RetryConfig
|
|
35
|
+
from .requestbodies import serialize_request_body, SerializedRequestBody
|
|
36
|
+
from .security import get_security, get_security_from_env
|
|
37
|
+
|
|
38
|
+
from .serializers import (
|
|
39
|
+
get_pydantic_model,
|
|
40
|
+
marshal_json,
|
|
41
|
+
unmarshal,
|
|
42
|
+
unmarshal_json,
|
|
43
|
+
serialize_decimal,
|
|
44
|
+
serialize_float,
|
|
45
|
+
serialize_int,
|
|
46
|
+
stream_to_text,
|
|
47
|
+
stream_to_text_async,
|
|
48
|
+
stream_to_bytes,
|
|
49
|
+
stream_to_bytes_async,
|
|
50
|
+
validate_const,
|
|
51
|
+
validate_decimal,
|
|
52
|
+
validate_float,
|
|
53
|
+
validate_int,
|
|
54
|
+
)
|
|
55
|
+
from .url import generate_url, template_url, remove_suffix
|
|
56
|
+
from .values import (
|
|
57
|
+
get_global_from_env,
|
|
58
|
+
match_content_type,
|
|
59
|
+
match_status_codes,
|
|
60
|
+
match_response,
|
|
61
|
+
cast_partial,
|
|
62
|
+
)
|
|
63
|
+
from .logger import Logger, get_body_content, get_default_logger
|
|
64
|
+
|
|
65
|
+
__all__ = [
|
|
66
|
+
"BackoffStrategy",
|
|
67
|
+
"FieldMetadata",
|
|
68
|
+
"find_metadata",
|
|
69
|
+
"FormMetadata",
|
|
70
|
+
"generate_url",
|
|
71
|
+
"get_body_content",
|
|
72
|
+
"get_default_logger",
|
|
73
|
+
"get_discriminator",
|
|
74
|
+
"parse_datetime",
|
|
75
|
+
"get_global_from_env",
|
|
76
|
+
"get_headers",
|
|
77
|
+
"get_pydantic_model",
|
|
78
|
+
"get_query_params",
|
|
79
|
+
"get_response_headers",
|
|
80
|
+
"get_security",
|
|
81
|
+
"get_security_from_env",
|
|
82
|
+
"HeaderMetadata",
|
|
83
|
+
"Logger",
|
|
84
|
+
"marshal_json",
|
|
85
|
+
"match_content_type",
|
|
86
|
+
"match_status_codes",
|
|
87
|
+
"match_response",
|
|
88
|
+
"MultipartFormMetadata",
|
|
89
|
+
"OpenEnumMeta",
|
|
90
|
+
"PathParamMetadata",
|
|
91
|
+
"QueryParamMetadata",
|
|
92
|
+
"remove_suffix",
|
|
93
|
+
"Retries",
|
|
94
|
+
"retry",
|
|
95
|
+
"retry_async",
|
|
96
|
+
"RetryConfig",
|
|
97
|
+
"RequestMetadata",
|
|
98
|
+
"SecurityMetadata",
|
|
99
|
+
"serialize_decimal",
|
|
100
|
+
"serialize_float",
|
|
101
|
+
"serialize_int",
|
|
102
|
+
"serialize_request_body",
|
|
103
|
+
"SerializedRequestBody",
|
|
104
|
+
"stream_to_text",
|
|
105
|
+
"stream_to_text_async",
|
|
106
|
+
"stream_to_bytes",
|
|
107
|
+
"stream_to_bytes_async",
|
|
108
|
+
"template_url",
|
|
109
|
+
"unmarshal",
|
|
110
|
+
"unmarshal_json",
|
|
111
|
+
"validate_decimal",
|
|
112
|
+
"validate_const",
|
|
113
|
+
"validate_float",
|
|
114
|
+
"validate_int",
|
|
115
|
+
"cast_partial",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
_dynamic_imports: dict[str, str] = {
|
|
119
|
+
"BackoffStrategy": ".retries",
|
|
120
|
+
"FieldMetadata": ".metadata",
|
|
121
|
+
"find_metadata": ".metadata",
|
|
122
|
+
"FormMetadata": ".metadata",
|
|
123
|
+
"generate_url": ".url",
|
|
124
|
+
"get_body_content": ".logger",
|
|
125
|
+
"get_default_logger": ".logger",
|
|
126
|
+
"get_discriminator": ".annotations",
|
|
127
|
+
"parse_datetime": ".datetimes",
|
|
128
|
+
"get_global_from_env": ".values",
|
|
129
|
+
"get_headers": ".headers",
|
|
130
|
+
"get_pydantic_model": ".serializers",
|
|
131
|
+
"get_query_params": ".queryparams",
|
|
132
|
+
"get_response_headers": ".headers",
|
|
133
|
+
"get_security": ".security",
|
|
134
|
+
"get_security_from_env": ".security",
|
|
135
|
+
"HeaderMetadata": ".metadata",
|
|
136
|
+
"Logger": ".logger",
|
|
137
|
+
"marshal_json": ".serializers",
|
|
138
|
+
"match_content_type": ".values",
|
|
139
|
+
"match_status_codes": ".values",
|
|
140
|
+
"match_response": ".values",
|
|
141
|
+
"MultipartFormMetadata": ".metadata",
|
|
142
|
+
"OpenEnumMeta": ".enums",
|
|
143
|
+
"PathParamMetadata": ".metadata",
|
|
144
|
+
"QueryParamMetadata": ".metadata",
|
|
145
|
+
"remove_suffix": ".url",
|
|
146
|
+
"Retries": ".retries",
|
|
147
|
+
"retry": ".retries",
|
|
148
|
+
"retry_async": ".retries",
|
|
149
|
+
"RetryConfig": ".retries",
|
|
150
|
+
"RequestMetadata": ".metadata",
|
|
151
|
+
"SecurityMetadata": ".metadata",
|
|
152
|
+
"serialize_decimal": ".serializers",
|
|
153
|
+
"serialize_float": ".serializers",
|
|
154
|
+
"serialize_int": ".serializers",
|
|
155
|
+
"serialize_request_body": ".requestbodies",
|
|
156
|
+
"SerializedRequestBody": ".requestbodies",
|
|
157
|
+
"stream_to_text": ".serializers",
|
|
158
|
+
"stream_to_text_async": ".serializers",
|
|
159
|
+
"stream_to_bytes": ".serializers",
|
|
160
|
+
"stream_to_bytes_async": ".serializers",
|
|
161
|
+
"template_url": ".url",
|
|
162
|
+
"unmarshal": ".serializers",
|
|
163
|
+
"unmarshal_json": ".serializers",
|
|
164
|
+
"validate_decimal": ".serializers",
|
|
165
|
+
"validate_const": ".serializers",
|
|
166
|
+
"validate_float": ".serializers",
|
|
167
|
+
"validate_int": ".serializers",
|
|
168
|
+
"cast_partial": ".values",
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def dynamic_import(modname, retries=3):
|
|
173
|
+
for attempt in range(retries):
|
|
174
|
+
try:
|
|
175
|
+
return import_module(modname, __package__)
|
|
176
|
+
except KeyError:
|
|
177
|
+
# Clear any half-initialized module and retry
|
|
178
|
+
sys.modules.pop(modname, None)
|
|
179
|
+
if attempt == retries - 1:
|
|
180
|
+
break
|
|
181
|
+
raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def __getattr__(attr_name: str) -> object:
|
|
185
|
+
module_name = _dynamic_imports.get(attr_name)
|
|
186
|
+
if module_name is None:
|
|
187
|
+
raise AttributeError(
|
|
188
|
+
f"no {attr_name} found in _dynamic_imports, module name -> {__name__} "
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
module = dynamic_import(module_name)
|
|
193
|
+
return getattr(module, attr_name)
|
|
194
|
+
except ImportError as e:
|
|
195
|
+
raise ImportError(
|
|
196
|
+
f"Failed to import {attr_name} from {module_name}: {e}"
|
|
197
|
+
) from e
|
|
198
|
+
except AttributeError as e:
|
|
199
|
+
raise AttributeError(
|
|
200
|
+
f"Failed to get {attr_name} from {module_name}: {e}"
|
|
201
|
+
) from e
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def __dir__():
|
|
205
|
+
lazy_attrs = builtins.list(_dynamic_imports.keys())
|
|
206
|
+
return builtins.sorted(lazy_attrs)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_discriminator(model: Any, fieldname: str, key: str) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Recursively search for the discriminator attribute in a model.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
model (Any): The model to search within.
|
|
13
|
+
fieldname (str): The name of the field to search for.
|
|
14
|
+
key (str): The key to search for in dictionaries.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
str: The name of the discriminator attribute.
|
|
18
|
+
|
|
19
|
+
Raises:
|
|
20
|
+
ValueError: If the discriminator attribute is not found.
|
|
21
|
+
"""
|
|
22
|
+
upper_fieldname = fieldname.upper()
|
|
23
|
+
|
|
24
|
+
def get_field_discriminator(field: Any) -> Optional[str]:
|
|
25
|
+
"""Search for the discriminator attribute in a given field."""
|
|
26
|
+
|
|
27
|
+
if isinstance(field, dict):
|
|
28
|
+
if key in field:
|
|
29
|
+
return f"{field[key]}"
|
|
30
|
+
|
|
31
|
+
if hasattr(field, fieldname):
|
|
32
|
+
attr = getattr(field, fieldname)
|
|
33
|
+
if isinstance(attr, Enum):
|
|
34
|
+
return f"{attr.value}"
|
|
35
|
+
return f"{attr}"
|
|
36
|
+
|
|
37
|
+
if hasattr(field, upper_fieldname):
|
|
38
|
+
attr = getattr(field, upper_fieldname)
|
|
39
|
+
if isinstance(attr, Enum):
|
|
40
|
+
return f"{attr.value}"
|
|
41
|
+
return f"{attr}"
|
|
42
|
+
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def search_nested_discriminator(obj: Any) -> Optional[str]:
|
|
46
|
+
"""Recursively search for discriminator in nested structures."""
|
|
47
|
+
# First try direct field lookup
|
|
48
|
+
discriminator = get_field_discriminator(obj)
|
|
49
|
+
if discriminator is not None:
|
|
50
|
+
return discriminator
|
|
51
|
+
|
|
52
|
+
# If it's a dict, search in nested values
|
|
53
|
+
if isinstance(obj, dict):
|
|
54
|
+
for value in obj.values():
|
|
55
|
+
if isinstance(value, list):
|
|
56
|
+
# Search in list items
|
|
57
|
+
for item in value:
|
|
58
|
+
nested_discriminator = search_nested_discriminator(item)
|
|
59
|
+
if nested_discriminator is not None:
|
|
60
|
+
return nested_discriminator
|
|
61
|
+
elif isinstance(value, dict):
|
|
62
|
+
# Search in nested dict
|
|
63
|
+
nested_discriminator = search_nested_discriminator(value)
|
|
64
|
+
if nested_discriminator is not None:
|
|
65
|
+
return nested_discriminator
|
|
66
|
+
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
if isinstance(model, list):
|
|
70
|
+
for field in model:
|
|
71
|
+
discriminator = search_nested_discriminator(field)
|
|
72
|
+
if discriminator is not None:
|
|
73
|
+
return discriminator
|
|
74
|
+
|
|
75
|
+
discriminator = search_nested_discriminator(model)
|
|
76
|
+
if discriminator is not None:
|
|
77
|
+
return discriminator
|
|
78
|
+
|
|
79
|
+
raise ValueError(f"Could not find discriminator field {fieldname} in {model}")
|