RESTFly 2.0.3__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.
restfly/_async.py ADDED
@@ -0,0 +1,1570 @@
1
+ from __future__ import annotations
2
+
3
+ import random
4
+ from asyncio import sleep
5
+ from collections.abc import AsyncIterator, Callable
6
+ from contextlib import asynccontextmanager
7
+ from ssl import SSLContext
8
+ from typing import Any, overload, override
9
+
10
+ from ._base import APIBaseEndpoint, APIClientBase, APIError
11
+ from ._errors import ErrorStatus, RetryError
12
+ from ._utils import assign_annotations, unmarshal
13
+ from .types import (
14
+ DEFAULT_LIMITS,
15
+ DEFAULT_MAX_REDIRECTS,
16
+ DEFAULT_TIMEOUT_CONFIG,
17
+ USE_CLIENT_DEFAULT,
18
+ AsyncBaseTransport,
19
+ AsyncClient,
20
+ AuthTypes,
21
+ CertTypes,
22
+ CookieTypes,
23
+ EventHook,
24
+ HeaderTypes,
25
+ HTTPMethods,
26
+ Limits,
27
+ Model,
28
+ ProxyTypes,
29
+ QueryParamTypes,
30
+ Request,
31
+ RequestContent,
32
+ RequestData,
33
+ RequestExtensions,
34
+ RequestFiles,
35
+ Response,
36
+ TimeoutTypes,
37
+ UseClientDefault,
38
+ XMLModel,
39
+ codes,
40
+ )
41
+
42
+
43
+ class AsyncHTTPClientVerbs:
44
+ async def _request(
45
+ self,
46
+ method: HTTPMethods,
47
+ path: str = "",
48
+ *,
49
+ response_model: type[Model | list[Model]] | None = None,
50
+ params: QueryParamTypes | None = None,
51
+ content: RequestContent | None = None,
52
+ data: RequestData | None = None,
53
+ files: RequestFiles | None = None,
54
+ headers: dict[str, str] | None = None,
55
+ json: Model | Any | None = None,
56
+ xml: XMLModel | str | bytes | None = None,
57
+ response_model_kwargs: dict[str, Any] | None = None,
58
+ request_model_kwargs: dict[str, Any] | None = None,
59
+ cookies: CookieTypes | None = None,
60
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
61
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
62
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
63
+ extensions: RequestExtensions | None = None,
64
+ max_retries: int | None = None,
65
+ error_map: dict[int, ErrorStatus] | None = None,
66
+ stream: bool = False,
67
+ ) -> Model | list[Model] | Response:
68
+ raise NotImplementedError
69
+
70
+ @asynccontextmanager
71
+ async def _stream(
72
+ self,
73
+ method: HTTPMethods,
74
+ path: str = "",
75
+ *,
76
+ params: QueryParamTypes | None = None,
77
+ content: RequestContent | None = None,
78
+ data: RequestData | None = None,
79
+ files: RequestFiles | None = None,
80
+ headers: dict[str, str] | None = None,
81
+ json: Model | Any | None = None,
82
+ xml: XMLModel | str | bytes | None = None,
83
+ request_model_kwargs: dict[str, Any] | None = None,
84
+ cookies: CookieTypes | None = None,
85
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
86
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
87
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
88
+ extensions: RequestExtensions | None = None,
89
+ max_retries: int | None = None,
90
+ error_map: dict[int, ErrorStatus] | None = None,
91
+ ) -> AsyncIterator[Response]:
92
+ """
93
+ Construct and send an HTTP request and stream the response back. This is an
94
+ alternative method to making a call to _request that also supports closing of
95
+ the response through the use of a context manager.
96
+
97
+ Args:
98
+ method:
99
+ The HTTP method used to make the call.
100
+ path:
101
+ URL to query.
102
+ request_model_kwargs:
103
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
104
+ marshalling the body of the data into the request.
105
+ params:
106
+ Request query parameters.
107
+ content:
108
+ Raw body of the request.
109
+ data:
110
+ URL form-encoded body for the request.
111
+ json:
112
+ Data object to marshal into JSON. Content passed with this parameter
113
+ will also set the ``Content-Type`` header to ``application/json``.
114
+ xml:
115
+ Data object to marshal into XML. Content passed with this parameter
116
+ will also set the ``Content-Type`` header to ``application/json``.
117
+ files:
118
+ A dictionary of upload files to include in the body of the request.
119
+ headers:
120
+ Request-specific headers.
121
+ cookies:
122
+ Request-specific cookies.
123
+ auth:
124
+ Request-specific authentication.
125
+ follow_redirects:
126
+ Should the client follow any redirects?
127
+ timeout:
128
+ Request-specific timeout settings.
129
+ extensions:
130
+ Any additional httpx extensions to pass to the client.
131
+ max_retries:
132
+ The maximum number of retries to attempt before giving up. Overloads
133
+ the client default.
134
+ error_map:
135
+ Replaces the client error map with this one instead.
136
+
137
+ Returns:
138
+ Returns the HTTPX Response object with streaming enabled.
139
+ """
140
+ response: Response = await self._request( # type: ignore[assignment] # ty: ignore[invalid-assignment]
141
+ method=method,
142
+ path=path,
143
+ params=params,
144
+ content=content,
145
+ data=data,
146
+ files=files,
147
+ headers=headers,
148
+ json=json,
149
+ xml=xml,
150
+ request_model_kwargs=request_model_kwargs,
151
+ cookies=cookies,
152
+ auth=auth,
153
+ follow_redirects=follow_redirects,
154
+ timeout=timeout,
155
+ extensions=extensions,
156
+ max_retries=max_retries,
157
+ error_map=error_map,
158
+ stream=True,
159
+ response_model=None,
160
+ response_model_kwargs=None,
161
+ )
162
+ try:
163
+ yield response
164
+ finally:
165
+ await response.aclose()
166
+
167
+ @overload
168
+ async def _get(
169
+ self,
170
+ path: str = ...,
171
+ *,
172
+ response_model: None = ...,
173
+ response_model_kwargs: dict[str, Any] | None = ...,
174
+ request_model_kwargs: dict[str, Any] | None = ...,
175
+ params: QueryParamTypes | None = ...,
176
+ headers: dict[str, str] | None = ...,
177
+ cookies: CookieTypes | None = ...,
178
+ auth: AuthTypes | UseClientDefault | None = ...,
179
+ follow_redirects: bool | UseClientDefault = ...,
180
+ timeout: TimeoutTypes | UseClientDefault = ...,
181
+ extensions: RequestExtensions | None = ...,
182
+ max_retries: int | None = ...,
183
+ error_map: dict[int, ErrorStatus] | None = ...,
184
+ ) -> Response: ...
185
+
186
+ @overload
187
+ async def _get(
188
+ self,
189
+ path: str = ...,
190
+ *,
191
+ response_model: type[Model],
192
+ response_model_kwargs: dict[str, Any] | None = ...,
193
+ request_model_kwargs: dict[str, Any] | None = ...,
194
+ params: QueryParamTypes | None = ...,
195
+ headers: dict[str, str] | None = ...,
196
+ cookies: CookieTypes | None = ...,
197
+ auth: AuthTypes | UseClientDefault | None = ...,
198
+ follow_redirects: bool | UseClientDefault = ...,
199
+ timeout: TimeoutTypes | UseClientDefault = ...,
200
+ extensions: RequestExtensions | None = ...,
201
+ max_retries: int | None = ...,
202
+ error_map: dict[int, ErrorStatus] | None = ...,
203
+ ) -> Model: ...
204
+
205
+ @overload
206
+ async def _get(
207
+ self,
208
+ path: str = ...,
209
+ *,
210
+ response_model: type[list[Model]],
211
+ response_model_kwargs: dict[str, Any] | None = ...,
212
+ request_model_kwargs: dict[str, Any] | None = ...,
213
+ params: QueryParamTypes | None = ...,
214
+ headers: dict[str, str] | None = ...,
215
+ cookies: CookieTypes | None = ...,
216
+ auth: AuthTypes | UseClientDefault | None = ...,
217
+ follow_redirects: bool | UseClientDefault = ...,
218
+ timeout: TimeoutTypes | UseClientDefault = ...,
219
+ extensions: RequestExtensions | None = ...,
220
+ max_retries: int | None = ...,
221
+ error_map: dict[int, ErrorStatus] | None = ...,
222
+ ) -> list[Model]: ...
223
+
224
+ async def _get(
225
+ self,
226
+ path: str = "",
227
+ *,
228
+ response_model: type[Model | list[Model]] | None = None,
229
+ response_model_kwargs: dict[str, Any] | None = None,
230
+ request_model_kwargs: dict[str, Any] | None = None,
231
+ params: QueryParamTypes | None = None,
232
+ headers: dict[str, str] | None = None,
233
+ cookies: CookieTypes | None = None,
234
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
235
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
236
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
237
+ extensions: RequestExtensions | None = None,
238
+ max_retries: int | None = None,
239
+ error_map: dict[int, ErrorStatus] | None = None,
240
+ ) -> Model | list[Model] | Response:
241
+ """
242
+ Construct and send an HTTP GET request.
243
+
244
+ Args:
245
+ path:
246
+ URL to query.
247
+ response_model:
248
+ Pydantic model to coerce the response into.
249
+ response_model_kwargs:
250
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
251
+ un-marshalling the response data.
252
+ params:
253
+ Request query parameters.
254
+ headers:
255
+ Request-specific headers.
256
+ cookies:
257
+ Request-specific cookies.
258
+ auth:
259
+ Request-specific authentication.
260
+ follow_redirects:
261
+ Should the client follow any redirects?
262
+ timeout:
263
+ Request-specific timeout settings.
264
+ extensions:
265
+ Any additional httpx extensions to pass to the client.
266
+ max_retries:
267
+ The maximum number of retries to attempt before giving up. Overloads
268
+ the client default.
269
+ error_map:
270
+ Replaces the client error map with this one instead.
271
+
272
+ Returns:
273
+ Returns the HTTPX Response object if no response_model is specified. If a
274
+ response_model _is_ specified, then the response will be coerced into the
275
+ response model and the instance of the model will be returned.
276
+ """
277
+ return await self._request(
278
+ method="GET",
279
+ path=path,
280
+ params=params,
281
+ headers=headers,
282
+ cookies=cookies,
283
+ auth=auth,
284
+ follow_redirects=follow_redirects,
285
+ timeout=timeout,
286
+ extensions=extensions,
287
+ response_model=response_model,
288
+ response_model_kwargs=response_model_kwargs,
289
+ request_model_kwargs=request_model_kwargs,
290
+ max_retries=max_retries,
291
+ error_map=error_map,
292
+ )
293
+
294
+ @overload
295
+ async def _post(
296
+ self,
297
+ path: str = ...,
298
+ *,
299
+ response_model: None = ...,
300
+ params: QueryParamTypes | None = ...,
301
+ content: RequestContent | None = ...,
302
+ data: RequestData | None = ...,
303
+ files: RequestFiles | None = ...,
304
+ json: Model | Any | None = ...,
305
+ xml: XMLModel | str | bytes | None = ...,
306
+ response_model_kwargs: dict[str, Any] | None = ...,
307
+ request_model_kwargs: dict[str, Any] | None = ...,
308
+ headers: dict[str, str] | None = ...,
309
+ cookies: CookieTypes | None = ...,
310
+ auth: AuthTypes | UseClientDefault | None = ...,
311
+ follow_redirects: bool | UseClientDefault = ...,
312
+ timeout: TimeoutTypes | UseClientDefault = ...,
313
+ extensions: RequestExtensions | None = ...,
314
+ max_retries: int | None = ...,
315
+ error_map: dict[int, ErrorStatus] | None = ...,
316
+ ) -> Response: ...
317
+
318
+ @overload
319
+ async def _post(
320
+ self,
321
+ path: str = ...,
322
+ *,
323
+ response_model: type[Model],
324
+ params: QueryParamTypes | None = ...,
325
+ content: RequestContent | None = ...,
326
+ data: RequestData | None = ...,
327
+ files: RequestFiles | None = ...,
328
+ json: Model | Any | None = ...,
329
+ xml: XMLModel | str | bytes | None = ...,
330
+ response_model_kwargs: dict[str, Any] | None = ...,
331
+ request_model_kwargs: dict[str, Any] | None = ...,
332
+ headers: dict[str, str] | None = ...,
333
+ cookies: CookieTypes | None = ...,
334
+ auth: AuthTypes | UseClientDefault | None = ...,
335
+ follow_redirects: bool | UseClientDefault = ...,
336
+ timeout: TimeoutTypes | UseClientDefault = ...,
337
+ extensions: RequestExtensions | None = ...,
338
+ max_retries: int | None = ...,
339
+ error_map: dict[int, ErrorStatus] | None = ...,
340
+ ) -> Model: ...
341
+
342
+ @overload
343
+ async def _post(
344
+ self,
345
+ path: str = ...,
346
+ *,
347
+ response_model: type[list[Model]],
348
+ params: QueryParamTypes | None = ...,
349
+ content: RequestContent | None = ...,
350
+ data: RequestData | None = ...,
351
+ files: RequestFiles | None = ...,
352
+ json: Model | Any | None = ...,
353
+ xml: XMLModel | str | bytes | None = ...,
354
+ response_model_kwargs: dict[str, Any] | None = ...,
355
+ request_model_kwargs: dict[str, Any] | None = ...,
356
+ headers: dict[str, str] | None = ...,
357
+ cookies: CookieTypes | None = ...,
358
+ auth: AuthTypes | UseClientDefault | None = ...,
359
+ follow_redirects: bool | UseClientDefault = ...,
360
+ timeout: TimeoutTypes | UseClientDefault = ...,
361
+ extensions: RequestExtensions | None = ...,
362
+ max_retries: int | None = ...,
363
+ error_map: dict[int, ErrorStatus] | None = ...,
364
+ ) -> list[Model]: ...
365
+
366
+ async def _post(
367
+ self,
368
+ path: str = "",
369
+ *,
370
+ params: QueryParamTypes | None = None,
371
+ content: RequestContent | None = None,
372
+ data: RequestData | None = None,
373
+ files: RequestFiles | None = None,
374
+ json: Model | Any | None = None,
375
+ xml: XMLModel | str | bytes | None = None,
376
+ headers: dict[str, str] | None = None,
377
+ response_model: type[Model | list[Model]] | None = None,
378
+ response_model_kwargs: dict[str, Any] | None = None,
379
+ request_model_kwargs: dict[str, Any] | None = None,
380
+ cookies: CookieTypes | None = None,
381
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
382
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
383
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
384
+ extensions: RequestExtensions | None = None,
385
+ max_retries: int | None = None,
386
+ error_map: dict[int, ErrorStatus] | None = None,
387
+ ) -> Model | list[Model] | Response:
388
+ """
389
+ Construct and send an HTTP POST request.
390
+
391
+ Args:
392
+ path:
393
+ URL to query.
394
+ response_model:
395
+ Pydantic model to coerce the response into.
396
+ response_model_kwargs:
397
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
398
+ un-marshalling the response data.
399
+ request_model_kwargs:
400
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
401
+ marshalling the body of the data into the request.
402
+ params:
403
+ Request query parameters.
404
+ content:
405
+ Raw body of the request.
406
+ data:
407
+ URL form-encoded body for the request.
408
+ json:
409
+ Data object to marshal into JSON. Content passed with this parameter
410
+ will also set the ``Content-Type`` header to ``application/json``.
411
+ xml:
412
+ Data object to marshal into XML. Content passed with this parameter
413
+ will also set the ``Content-Type`` header to ``application/json``.
414
+ files:
415
+ A dictionary of upload files to include in the body of the request.
416
+ headers:
417
+ Request-specific headers.
418
+ cookies:
419
+ Request-specific cookies.
420
+ auth:
421
+ Request-specific authentication.
422
+ follow_redirects:
423
+ Should the client follow any redirects?
424
+ timeout:
425
+ Request-specific timeout settings.
426
+ extensions:
427
+ Any additional httpx extensions to pass to the client.
428
+ max_retries:
429
+ The maximum number of retries to attempt before giving up. Overloads
430
+ the client default.
431
+ error_map:
432
+ Replaces the client error map with this one instead.
433
+
434
+ Returns:
435
+ Returns the HTTPX Response object if no response_model is specified. If a
436
+ response_model _is_ specified, then the response will be coerced into the
437
+ response model and the instance of the model will be returned.
438
+ """
439
+ return await self._request(
440
+ method="POST",
441
+ path=path,
442
+ params=params,
443
+ content=content,
444
+ data=data,
445
+ files=files,
446
+ json=json,
447
+ xml=xml,
448
+ headers=headers,
449
+ cookies=cookies,
450
+ auth=auth,
451
+ follow_redirects=follow_redirects,
452
+ timeout=timeout,
453
+ extensions=extensions,
454
+ response_model=response_model,
455
+ response_model_kwargs=response_model_kwargs,
456
+ request_model_kwargs=request_model_kwargs,
457
+ max_retries=max_retries,
458
+ error_map=error_map,
459
+ )
460
+
461
+ @overload
462
+ async def _put(
463
+ self,
464
+ path: str = ...,
465
+ *,
466
+ response_model: None = ...,
467
+ params: QueryParamTypes | None = ...,
468
+ content: RequestContent | None = ...,
469
+ data: RequestData | None = ...,
470
+ files: RequestFiles | None = ...,
471
+ json: Model | Any | None = ...,
472
+ xml: XMLModel | str | bytes | None = ...,
473
+ response_model_kwargs: dict[str, Any] | None = ...,
474
+ request_model_kwargs: dict[str, Any] | None = ...,
475
+ headers: dict[str, str] | None = ...,
476
+ cookies: CookieTypes | None = ...,
477
+ auth: AuthTypes | UseClientDefault | None = ...,
478
+ follow_redirects: bool | UseClientDefault = ...,
479
+ timeout: TimeoutTypes | UseClientDefault = ...,
480
+ extensions: RequestExtensions | None = ...,
481
+ max_retries: int | None = ...,
482
+ error_map: dict[int, ErrorStatus] | None = ...,
483
+ ) -> Response: ...
484
+
485
+ @overload
486
+ async def _put(
487
+ self,
488
+ path: str = ...,
489
+ *,
490
+ response_model: type[Model],
491
+ params: QueryParamTypes | None = ...,
492
+ content: RequestContent | None = ...,
493
+ data: RequestData | None = ...,
494
+ files: RequestFiles | None = ...,
495
+ json: Model | Any | None = ...,
496
+ xml: XMLModel | str | bytes | None = ...,
497
+ response_model_kwargs: dict[str, Any] | None = ...,
498
+ request_model_kwargs: dict[str, Any] | None = ...,
499
+ headers: dict[str, str] | None = ...,
500
+ cookies: CookieTypes | None = ...,
501
+ auth: AuthTypes | UseClientDefault | None = ...,
502
+ follow_redirects: bool | UseClientDefault = ...,
503
+ timeout: TimeoutTypes | UseClientDefault = ...,
504
+ extensions: RequestExtensions | None = ...,
505
+ max_retries: int | None = ...,
506
+ error_map: dict[int, ErrorStatus] | None = ...,
507
+ ) -> Model: ...
508
+
509
+ @overload
510
+ async def _put(
511
+ self,
512
+ path: str = ...,
513
+ *,
514
+ response_model: type[list[Model]],
515
+ params: QueryParamTypes | None = ...,
516
+ content: RequestContent | None = ...,
517
+ data: RequestData | None = ...,
518
+ files: RequestFiles | None = ...,
519
+ json: Model | Any | None = ...,
520
+ xml: XMLModel | str | bytes | None = ...,
521
+ response_model_kwargs: dict[str, Any] | None = ...,
522
+ request_model_kwargs: dict[str, Any] | None = ...,
523
+ headers: dict[str, str] | None = ...,
524
+ cookies: CookieTypes | None = ...,
525
+ auth: AuthTypes | UseClientDefault | None = ...,
526
+ follow_redirects: bool | UseClientDefault = ...,
527
+ timeout: TimeoutTypes | UseClientDefault = ...,
528
+ extensions: RequestExtensions | None = ...,
529
+ max_retries: int | None = ...,
530
+ error_map: dict[int, ErrorStatus] | None = ...,
531
+ ) -> list[Model]: ...
532
+
533
+ async def _put(
534
+ self,
535
+ path: str = "",
536
+ *,
537
+ params: QueryParamTypes | None = None,
538
+ content: RequestContent | None = None,
539
+ data: RequestData | None = None,
540
+ files: RequestFiles | None = None,
541
+ json: Model | Any | None = None,
542
+ xml: XMLModel | str | bytes | None = None,
543
+ headers: dict[str, str] | None = None,
544
+ response_model: type[Model | list[Model]] | None = None,
545
+ response_model_kwargs: dict[str, Any] | None = None,
546
+ request_model_kwargs: dict[str, Any] | None = None,
547
+ cookies: CookieTypes | None = None,
548
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
549
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
550
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
551
+ extensions: RequestExtensions | None = None,
552
+ max_retries: int | None = None,
553
+ error_map: dict[int, ErrorStatus] | None = None,
554
+ ) -> Model | list[Model] | Response:
555
+ """
556
+ Construct and send an HTTP PUT request.
557
+
558
+ Args:
559
+ path:
560
+ URL to query.
561
+ response_model:
562
+ Pydantic model to coerce the response into.
563
+ response_model_kwargs:
564
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
565
+ un-marshalling the response data.
566
+ request_model_kwargs:
567
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
568
+ marshalling the body of the data into the request.
569
+ params:
570
+ Request query parameters.
571
+ content:
572
+ Raw body of the request.
573
+ data:
574
+ URL form-encoded body for the request.
575
+ json:
576
+ Data object to marshal into JSON. Content passed with this parameter
577
+ will also set the ``Content-Type`` header to ``application/json``.
578
+ xml:
579
+ Data object to marshal into XML. Content passed with this parameter
580
+ will also set the ``Content-Type`` header to ``application/json``.
581
+ files:
582
+ A dictionary of upload files to include in the body of the request.
583
+ headers:
584
+ Request-specific headers.
585
+ cookies:
586
+ Request-specific cookies.
587
+ auth:
588
+ Request-specific authentication.
589
+ follow_redirects:
590
+ Should the client follow any redirects?
591
+ timeout:
592
+ Request-specific timeout settings.
593
+ extensions:
594
+ Any additional httpx extensions to pass to the client.
595
+ max_retries:
596
+ The maximum number of retries to attempt before giving up. Overloads
597
+ the client default.
598
+ error_map:
599
+ Replaces the client error map with this one instead.
600
+
601
+ Returns:
602
+ Returns the HTTPX Response object if no response_model is specified. If a
603
+ response_model _is_ specified, then the response will be coerced into the
604
+ response model and the instance of the model will be returned.
605
+ """
606
+ return await self._request(
607
+ method="PUT",
608
+ path=path,
609
+ params=params,
610
+ content=content,
611
+ data=data,
612
+ files=files,
613
+ json=json,
614
+ xml=xml,
615
+ headers=headers,
616
+ cookies=cookies,
617
+ auth=auth,
618
+ follow_redirects=follow_redirects,
619
+ timeout=timeout,
620
+ extensions=extensions,
621
+ response_model=response_model,
622
+ response_model_kwargs=response_model_kwargs,
623
+ request_model_kwargs=request_model_kwargs,
624
+ max_retries=max_retries,
625
+ error_map=error_map,
626
+ )
627
+
628
+ @overload
629
+ async def _patch(
630
+ self,
631
+ path: str = ...,
632
+ *,
633
+ response_model: None = ...,
634
+ params: QueryParamTypes | None = ...,
635
+ content: RequestContent | None = ...,
636
+ data: RequestData | None = ...,
637
+ files: RequestFiles | None = ...,
638
+ json: Model | Any | None = ...,
639
+ xml: XMLModel | str | bytes | None = ...,
640
+ response_model_kwargs: dict[str, Any] | None = ...,
641
+ request_model_kwargs: dict[str, Any] | None = ...,
642
+ headers: dict[str, str] | None = ...,
643
+ cookies: CookieTypes | None = ...,
644
+ auth: AuthTypes | UseClientDefault | None = ...,
645
+ follow_redirects: bool | UseClientDefault = ...,
646
+ timeout: TimeoutTypes | UseClientDefault = ...,
647
+ extensions: RequestExtensions | None = ...,
648
+ max_retries: int | None = ...,
649
+ error_map: dict[int, ErrorStatus] | None = ...,
650
+ ) -> Response: ...
651
+
652
+ @overload
653
+ async def _patch(
654
+ self,
655
+ path: str = ...,
656
+ *,
657
+ response_model: type[Model],
658
+ params: QueryParamTypes | None = ...,
659
+ content: RequestContent | None = ...,
660
+ data: RequestData | None = ...,
661
+ files: RequestFiles | None = ...,
662
+ json: Model | Any | None = ...,
663
+ xml: XMLModel | str | bytes | None = ...,
664
+ response_model_kwargs: dict[str, Any] | None = ...,
665
+ request_model_kwargs: dict[str, Any] | None = ...,
666
+ headers: dict[str, str] | None = ...,
667
+ cookies: CookieTypes | None = ...,
668
+ auth: AuthTypes | UseClientDefault | None = ...,
669
+ follow_redirects: bool | UseClientDefault = ...,
670
+ timeout: TimeoutTypes | UseClientDefault = ...,
671
+ extensions: RequestExtensions | None = ...,
672
+ max_retries: int | None = ...,
673
+ error_map: dict[int, ErrorStatus] | None = ...,
674
+ ) -> Model: ...
675
+
676
+ @overload
677
+ async def _patch(
678
+ self,
679
+ path: str = ...,
680
+ *,
681
+ response_model: type[list[Model]],
682
+ params: QueryParamTypes | None = ...,
683
+ content: RequestContent | None = ...,
684
+ data: RequestData | None = ...,
685
+ files: RequestFiles | None = ...,
686
+ json: Model | Any | None = ...,
687
+ xml: XMLModel | str | bytes | None = ...,
688
+ response_model_kwargs: dict[str, Any] | None = ...,
689
+ request_model_kwargs: dict[str, Any] | None = ...,
690
+ headers: dict[str, str] | None = ...,
691
+ cookies: CookieTypes | None = ...,
692
+ auth: AuthTypes | UseClientDefault | None = ...,
693
+ follow_redirects: bool | UseClientDefault = ...,
694
+ timeout: TimeoutTypes | UseClientDefault = ...,
695
+ extensions: RequestExtensions | None = ...,
696
+ max_retries: int | None = ...,
697
+ error_map: dict[int, ErrorStatus] | None = ...,
698
+ ) -> list[Model]: ...
699
+
700
+ async def _patch(
701
+ self,
702
+ path: str = "",
703
+ *,
704
+ params: QueryParamTypes | None = None,
705
+ content: RequestContent | None = None,
706
+ data: RequestData | None = None,
707
+ files: RequestFiles | None = None,
708
+ json: Model | Any | None = None,
709
+ xml: XMLModel | str | bytes | None = None,
710
+ headers: dict[str, str] | None = None,
711
+ response_model: type[Model | list[Model]] | None = None,
712
+ response_model_kwargs: dict[str, Any] | None = None,
713
+ request_model_kwargs: dict[str, Any] | None = None,
714
+ cookies: CookieTypes | None = None,
715
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
716
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
717
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
718
+ extensions: RequestExtensions | None = None,
719
+ max_retries: int | None = None,
720
+ error_map: dict[int, ErrorStatus] | None = None,
721
+ ) -> Model | list[Model] | Response:
722
+ """
723
+ Construct and send an HTTP PATCH request.
724
+
725
+ Args:
726
+ path:
727
+ URL to query.
728
+ response_model:
729
+ Pydantic model to coerce the response into.
730
+ response_model_kwargs:
731
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
732
+ un-marshalling the response data.
733
+ request_model_kwargs:
734
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
735
+ marshalling the body of the data into the request.
736
+ params:
737
+ Request query parameters.
738
+ content:
739
+ Raw body of the request.
740
+ data:
741
+ URL form-encoded body for the request.
742
+ json:
743
+ Data object to marshal into JSON. Content passed with this parameter
744
+ will also set the ``Content-Type`` header to ``application/json``.
745
+ xml:
746
+ Data object to marshal into XML. Content passed with this parameter
747
+ will also set the ``Content-Type`` header to ``application/json``.
748
+ files:
749
+ A dictionary of upload files to include in the body of the request.
750
+ headers:
751
+ Request-specific headers.
752
+ cookies:
753
+ Request-specific cookies.
754
+ auth:
755
+ Request-specific authentication.
756
+ follow_redirects:
757
+ Should the client follow any redirects?
758
+ timeout:
759
+ Request-specific timeout settings.
760
+ extensions:
761
+ Any additional httpx extensions to pass to the client.
762
+ max_retries:
763
+ The maximum number of retries to attempt before giving up. Overloads
764
+ the client default.
765
+ error_map:
766
+ Replaces the client error map with this one instead.
767
+
768
+ Returns:
769
+ Returns the HTTPX Response object if no response_model is specified. If a
770
+ response_model _is_ specified, then the response will be coerced into the
771
+ response model and the instance of the model will be returned.
772
+ """
773
+ return await self._request(
774
+ method="PATCH",
775
+ path=path,
776
+ params=params,
777
+ content=content,
778
+ data=data,
779
+ files=files,
780
+ json=json,
781
+ xml=xml,
782
+ headers=headers,
783
+ cookies=cookies,
784
+ auth=auth,
785
+ follow_redirects=follow_redirects,
786
+ timeout=timeout,
787
+ extensions=extensions,
788
+ response_model=response_model,
789
+ response_model_kwargs=response_model_kwargs,
790
+ request_model_kwargs=request_model_kwargs,
791
+ max_retries=max_retries,
792
+ error_map=error_map,
793
+ )
794
+
795
+ @overload
796
+ async def _delete(
797
+ self,
798
+ path: str = ...,
799
+ *,
800
+ response_model: None = ...,
801
+ params: QueryParamTypes | None = ...,
802
+ content: RequestContent | None = ...,
803
+ data: RequestData | None = ...,
804
+ files: RequestFiles | None = ...,
805
+ json: Model | Any | None = ...,
806
+ xml: XMLModel | str | bytes | None = ...,
807
+ response_model_kwargs: dict[str, Any] | None = ...,
808
+ request_model_kwargs: dict[str, Any] | None = ...,
809
+ headers: dict[str, str] | None = ...,
810
+ cookies: CookieTypes | None = ...,
811
+ auth: AuthTypes | UseClientDefault | None = ...,
812
+ follow_redirects: bool | UseClientDefault = ...,
813
+ timeout: TimeoutTypes | UseClientDefault = ...,
814
+ extensions: RequestExtensions | None = ...,
815
+ max_retries: int | None = ...,
816
+ error_map: dict[int, ErrorStatus] | None = ...,
817
+ ) -> Response: ...
818
+
819
+ @overload
820
+ async def _delete(
821
+ self,
822
+ path: str = ...,
823
+ *,
824
+ response_model: type[Model],
825
+ params: QueryParamTypes | None = ...,
826
+ content: RequestContent | None = ...,
827
+ data: RequestData | None = ...,
828
+ files: RequestFiles | None = ...,
829
+ json: Model | Any | None = ...,
830
+ xml: XMLModel | str | bytes | None = ...,
831
+ response_model_kwargs: dict[str, Any] | None = ...,
832
+ request_model_kwargs: dict[str, Any] | None = ...,
833
+ headers: dict[str, str] | None = ...,
834
+ cookies: CookieTypes | None = ...,
835
+ auth: AuthTypes | UseClientDefault | None = ...,
836
+ follow_redirects: bool | UseClientDefault = ...,
837
+ timeout: TimeoutTypes | UseClientDefault = ...,
838
+ extensions: RequestExtensions | None = ...,
839
+ max_retries: int | None = ...,
840
+ error_map: dict[int, ErrorStatus] | None = ...,
841
+ ) -> Model: ...
842
+
843
+ @overload
844
+ async def _delete(
845
+ self,
846
+ path: str = ...,
847
+ *,
848
+ response_model: type[list[Model]],
849
+ params: QueryParamTypes | None = ...,
850
+ content: RequestContent | None = ...,
851
+ data: RequestData | None = ...,
852
+ files: RequestFiles | None = ...,
853
+ json: Model | Any | None = ...,
854
+ xml: XMLModel | str | bytes | None = ...,
855
+ response_model_kwargs: dict[str, Any] | None = ...,
856
+ request_model_kwargs: dict[str, Any] | None = ...,
857
+ headers: dict[str, str] | None = ...,
858
+ cookies: CookieTypes | None = ...,
859
+ auth: AuthTypes | UseClientDefault | None = ...,
860
+ follow_redirects: bool | UseClientDefault = ...,
861
+ timeout: TimeoutTypes | UseClientDefault = ...,
862
+ extensions: RequestExtensions | None = ...,
863
+ max_retries: int | None = ...,
864
+ error_map: dict[int, ErrorStatus] | None = ...,
865
+ ) -> list[Model]: ...
866
+
867
+ async def _delete(
868
+ self,
869
+ path: str = "",
870
+ *,
871
+ params: QueryParamTypes | None = None,
872
+ content: RequestContent | None = None,
873
+ data: RequestData | None = None,
874
+ files: RequestFiles | None = None,
875
+ json: Model | Any | None = None,
876
+ xml: XMLModel | str | bytes | None = None,
877
+ headers: dict[str, str] | None = None,
878
+ response_model: type[Model | list[Model]] | None = None,
879
+ response_model_kwargs: dict[str, Any] | None = None,
880
+ request_model_kwargs: dict[str, Any] | None = None,
881
+ cookies: CookieTypes | None = None,
882
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
883
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
884
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
885
+ extensions: RequestExtensions | None = None,
886
+ max_retries: int | None = None,
887
+ error_map: dict[int, ErrorStatus] | None = None,
888
+ ) -> Model | list[Model] | Response:
889
+ """
890
+ Construct and send an HTTP DELETE request.
891
+
892
+ Args:
893
+ path:
894
+ URL to query.
895
+ response_model:
896
+ Pydantic model to coerce the response into.
897
+ response_model_kwargs:
898
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
899
+ un-marshalling the response data.
900
+ request_model_kwargs:
901
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
902
+ marshalling the body of the data into the request.
903
+ params:
904
+ Request query parameters.
905
+ content:
906
+ Raw body of the request.
907
+ data:
908
+ URL form-encoded body for the request.
909
+ json:
910
+ Data object to marshal into JSON. Content passed with this parameter
911
+ will also set the ``Content-Type`` header to ``application/json``.
912
+ xml:
913
+ Data object to marshal into XML. Content passed with this parameter
914
+ will also set the ``Content-Type`` header to ``application/json``.
915
+ files:
916
+ A dictionary of upload files to include in the body of the request.
917
+ headers:
918
+ Request-specific headers.
919
+ cookies:
920
+ Request-specific cookies.
921
+ auth:
922
+ Request-specific authentication.
923
+ follow_redirects:
924
+ Should the client follow any redirects?
925
+ timeout:
926
+ Request-specific timeout settings.
927
+ extensions:
928
+ Any additional httpx extensions to pass to the client.
929
+ max_retries:
930
+ The maximum number of retries to attempt before giving up. Overloads
931
+ the client default.
932
+ error_map:
933
+ Replaces the client error map with this one instead.
934
+
935
+ Returns:
936
+ Returns the HTTPX Response object if no response_model is specified. If a
937
+ response_model _is_ specified, then the response will be coerced into the
938
+ response model and the instance of the model will be returned.
939
+ """
940
+ return await self._request(
941
+ method="DELETE",
942
+ path=path,
943
+ params=params,
944
+ content=content,
945
+ data=data,
946
+ files=files,
947
+ json=json,
948
+ xml=xml,
949
+ headers=headers,
950
+ cookies=cookies,
951
+ auth=auth,
952
+ follow_redirects=follow_redirects,
953
+ timeout=timeout,
954
+ extensions=extensions,
955
+ response_model=response_model,
956
+ response_model_kwargs=response_model_kwargs,
957
+ request_model_kwargs=request_model_kwargs,
958
+ max_retries=max_retries,
959
+ error_map=error_map,
960
+ )
961
+
962
+
963
+ class AsyncAPIEndpoint(APIBaseEndpoint, AsyncHTTPClientVerbs):
964
+ _client: AsyncAPIClient
965
+
966
+ def __init__(self, client: AsyncAPIClient | AsyncAPIEndpoint) -> None:
967
+ super().__init__(client)
968
+
969
+ @overload
970
+ async def _request(
971
+ self,
972
+ method: HTTPMethods,
973
+ path: str = "",
974
+ *,
975
+ response_model: None = ...,
976
+ params: QueryParamTypes | None = ...,
977
+ content: RequestContent | None = ...,
978
+ data: RequestData | None = ...,
979
+ files: RequestFiles | None = ...,
980
+ json: Model | Any | None = ...,
981
+ xml: XMLModel | str | bytes | None = ...,
982
+ response_model_kwargs: dict[str, Any] | None = ...,
983
+ request_model_kwargs: dict[str, Any] | None = ...,
984
+ headers: dict[str, str] | None = ...,
985
+ cookies: CookieTypes | None = ...,
986
+ auth: AuthTypes | UseClientDefault | None = ...,
987
+ follow_redirects: bool | UseClientDefault = ...,
988
+ timeout: TimeoutTypes | UseClientDefault = ...,
989
+ extensions: RequestExtensions | None = ...,
990
+ max_retries: int | None = ...,
991
+ error_map: dict[int, ErrorStatus] | None = ...,
992
+ stream: bool = ...,
993
+ ) -> Response: ...
994
+
995
+ @overload
996
+ async def _request(
997
+ self,
998
+ method: HTTPMethods,
999
+ path: str = "",
1000
+ *,
1001
+ response_model: type[Model],
1002
+ params: QueryParamTypes | None = ...,
1003
+ content: RequestContent | None = ...,
1004
+ data: RequestData | None = ...,
1005
+ files: RequestFiles | None = ...,
1006
+ json: Model | Any | None = ...,
1007
+ xml: XMLModel | str | bytes | None = ...,
1008
+ response_model_kwargs: dict[str, Any] | None = ...,
1009
+ request_model_kwargs: dict[str, Any] | None = ...,
1010
+ headers: dict[str, str] | None = ...,
1011
+ cookies: CookieTypes | None = ...,
1012
+ auth: AuthTypes | UseClientDefault | None = ...,
1013
+ follow_redirects: bool | UseClientDefault = ...,
1014
+ timeout: TimeoutTypes | UseClientDefault = ...,
1015
+ extensions: RequestExtensions | None = ...,
1016
+ max_retries: int | None = ...,
1017
+ error_map: dict[int, ErrorStatus] | None = ...,
1018
+ stream: bool = False,
1019
+ ) -> Model: ...
1020
+
1021
+ @overload
1022
+ async def _request(
1023
+ self,
1024
+ method: HTTPMethods,
1025
+ path: str = "",
1026
+ *,
1027
+ response_model: type[list[Model]],
1028
+ params: QueryParamTypes | None = ...,
1029
+ content: RequestContent | None = ...,
1030
+ data: RequestData | None = ...,
1031
+ files: RequestFiles | None = ...,
1032
+ json: Model | Any | None = ...,
1033
+ xml: XMLModel | str | bytes | None = ...,
1034
+ response_model_kwargs: dict[str, Any] | None = ...,
1035
+ request_model_kwargs: dict[str, Any] | None = ...,
1036
+ headers: dict[str, str] | None = ...,
1037
+ cookies: CookieTypes | None = ...,
1038
+ auth: AuthTypes | UseClientDefault | None = ...,
1039
+ follow_redirects: bool | UseClientDefault = ...,
1040
+ timeout: TimeoutTypes | UseClientDefault = ...,
1041
+ extensions: RequestExtensions | None = ...,
1042
+ max_retries: int | None = ...,
1043
+ error_map: dict[int, ErrorStatus] | None = ...,
1044
+ stream: bool = False,
1045
+ ) -> list[Model]: ...
1046
+
1047
+ @overload
1048
+ async def _request(
1049
+ self,
1050
+ method: HTTPMethods,
1051
+ path: str = "",
1052
+ *,
1053
+ response_model: type[Model | list[Model]] | None = ...,
1054
+ params: QueryParamTypes | None = ...,
1055
+ content: RequestContent | None = ...,
1056
+ data: RequestData | None = ...,
1057
+ files: RequestFiles | None = ...,
1058
+ json: Model | Any | None = ...,
1059
+ xml: XMLModel | str | bytes | None = ...,
1060
+ response_model_kwargs: dict[str, Any] | None = ...,
1061
+ request_model_kwargs: dict[str, Any] | None = ...,
1062
+ headers: dict[str, str] | None = ...,
1063
+ cookies: CookieTypes | None = ...,
1064
+ auth: AuthTypes | UseClientDefault | None = ...,
1065
+ follow_redirects: bool | UseClientDefault = ...,
1066
+ timeout: TimeoutTypes | UseClientDefault = ...,
1067
+ extensions: RequestExtensions | None = ...,
1068
+ max_retries: int | None = ...,
1069
+ error_map: dict[int, ErrorStatus] | None = ...,
1070
+ stream: bool = ...,
1071
+ ) -> Model | list[Model] | Response: ...
1072
+
1073
+ @override
1074
+ async def _request(
1075
+ self,
1076
+ method: HTTPMethods,
1077
+ path: str = "",
1078
+ *,
1079
+ params: QueryParamTypes | None = None,
1080
+ content: RequestContent | None = None,
1081
+ data: RequestData | None = None,
1082
+ files: RequestFiles | None = None,
1083
+ headers: dict[str, str] | None = None,
1084
+ json: Model | Any | None = None,
1085
+ xml: XMLModel | str | bytes | None = None,
1086
+ response_model: type[Model | list[Model]] | None = None,
1087
+ response_model_kwargs: dict[str, Any] | None = None,
1088
+ request_model_kwargs: dict[str, Any] | None = None,
1089
+ cookies: CookieTypes | None = None,
1090
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
1091
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
1092
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
1093
+ extensions: RequestExtensions | None = None,
1094
+ max_retries: int | None = None,
1095
+ error_map: dict[int, ErrorStatus] | None = None,
1096
+ stream: bool = False,
1097
+ ) -> Model | list[Model] | Response:
1098
+ """
1099
+ Construct and send an HTTP request.
1100
+
1101
+ Args:
1102
+ method:
1103
+ The HTTP method used to make the call.
1104
+ path:
1105
+ URL to query.
1106
+ response_model:
1107
+ Pydantic model to coerce the response into.
1108
+ response_model_kwargs:
1109
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
1110
+ un-marshalling the response data.
1111
+ request_model_kwargs:
1112
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
1113
+ marshalling the body of the data into the request.
1114
+ params:
1115
+ Request query parameters.
1116
+ content:
1117
+ Raw body of the request.
1118
+ data:
1119
+ URL form-encoded body for the request.
1120
+ json:
1121
+ Data object to marshal into JSON. Content passed with this parameter
1122
+ will also set the ``Content-Type`` header to ``application/json``.
1123
+ xml:
1124
+ Data object to marshal into XML. Content passed with this parameter
1125
+ will also set the ``Content-Type`` header to ``application/json``.
1126
+ files:
1127
+ A dictionary of upload files to include in the body of the request.
1128
+ headers:
1129
+ Request-specific headers.
1130
+ cookies:
1131
+ Request-specific cookies.
1132
+ auth:
1133
+ Request-specific authentication.
1134
+ follow_redirects:
1135
+ Should the client follow any redirects?
1136
+ timeout:
1137
+ Request-specific timeout settings.
1138
+ extensions:
1139
+ Any additional httpx extensions to pass to the client.
1140
+ max_retries:
1141
+ The maximum number of retries to attempt before giving up. Overloads
1142
+ the client default.
1143
+ error_map:
1144
+ Replaces the client error map with this one instead.
1145
+
1146
+ Returns:
1147
+ Returns the HTTPX Response object if no response_model is specified. If a
1148
+ response_model _is_ specified, then the response will be coerced into the
1149
+ response model and the instance of the model will be returned.
1150
+ """
1151
+ if self._path is not None:
1152
+ path = f"{self._path}{path}"
1153
+
1154
+ return await self._client._request(
1155
+ method=method,
1156
+ path=path,
1157
+ params=params,
1158
+ headers=headers,
1159
+ cookies=cookies,
1160
+ auth=auth,
1161
+ follow_redirects=follow_redirects,
1162
+ timeout=timeout,
1163
+ extensions=extensions,
1164
+ json=json,
1165
+ xml=xml,
1166
+ content=content,
1167
+ data=data,
1168
+ files=files,
1169
+ response_model=response_model,
1170
+ max_retries=max_retries,
1171
+ response_model_kwargs=response_model_kwargs,
1172
+ request_model_kwargs=request_model_kwargs,
1173
+ error_map=error_map,
1174
+ stream=stream,
1175
+ )
1176
+
1177
+
1178
+ class AsyncAPIClient(APIClientBase, AsyncHTTPClientVerbs):
1179
+ __client_class__: type[AsyncClient] = AsyncClient
1180
+ __endpoint_class__: type[AsyncAPIEndpoint] = AsyncAPIEndpoint
1181
+ _client: AsyncClient
1182
+
1183
+ @override
1184
+ def __assign_annotations__(self) -> None:
1185
+ """
1186
+ Any public annotations that are a subclass of the APIEndpoint class will be
1187
+ assigned at initialization of the object through this method.
1188
+ """
1189
+ assign_annotations(self, AsyncAPIEndpoint)
1190
+
1191
+ async def __aenter__(self):
1192
+ """
1193
+ Async Context Manager __aenter__ dunder. See PEP-343 for more details.
1194
+ """
1195
+ return self
1196
+
1197
+ async def __aexit__(self, exc_type, exc_value, exc_traceback):
1198
+ """
1199
+ Async Context Manager __aexit__ dunder. See PEP-343 for more details.
1200
+ """
1201
+ return self._deauthenticate()
1202
+
1203
+ def __init__(
1204
+ self,
1205
+ *,
1206
+ auth: AuthTypes | None = None,
1207
+ params: QueryParamTypes | None = None,
1208
+ headers: HeaderTypes | None = None,
1209
+ cookies: CookieTypes | None = None,
1210
+ verify: SSLContext | str | bool = True,
1211
+ cert: CertTypes | None = None,
1212
+ http1: bool = True,
1213
+ http2: bool = False,
1214
+ proxy: ProxyTypes | None = None,
1215
+ mounts: (dict[str, AsyncBaseTransport | None]) | None = None,
1216
+ timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
1217
+ follow_redirects: bool = False,
1218
+ limits: Limits = DEFAULT_LIMITS,
1219
+ max_redirects: int = DEFAULT_MAX_REDIRECTS,
1220
+ event_hooks: (dict[str, list[EventHook]]) | None = None,
1221
+ base_url: str | None = None,
1222
+ transport: AsyncBaseTransport | None = None,
1223
+ trust_env: bool = True,
1224
+ default_encoding: str | Callable[[bytes], str] = "utf-8",
1225
+ vendor: str = "unknown",
1226
+ product: str = "unknown",
1227
+ build: str = "unknown",
1228
+ retry_max: int = 5,
1229
+ json_load_kwargs: dict[str, Any] | None = None,
1230
+ json_dump_kwargs: dict[str, Any] | None = None,
1231
+ xml_load_kwargs: dict[str, Any] | None = None,
1232
+ xml_dump_kwargs: dict[str, Any] | None = None,
1233
+ error_map: dict[int, ErrorStatus] | None = None,
1234
+ error_class: type[APIError] | None = None,
1235
+ ) -> None:
1236
+ # Add the class event hooks to loop in the logging facilities.
1237
+ event_hooks = {} if event_hooks is None else event_hooks
1238
+ event_hooks = {
1239
+ "request": [self._request_hook] + list(event_hooks.get("request", [])),
1240
+ "response": [self._response_hook] + list(event_hooks.get("response", [])),
1241
+ }
1242
+ super().__init__(
1243
+ auth=auth,
1244
+ params=params,
1245
+ headers=headers,
1246
+ cookies=cookies,
1247
+ verify=verify,
1248
+ cert=cert,
1249
+ http1=http1,
1250
+ http2=http2,
1251
+ proxy=proxy,
1252
+ mounts=mounts,
1253
+ timeout=timeout,
1254
+ follow_redirects=follow_redirects,
1255
+ limits=limits,
1256
+ max_redirects=max_redirects,
1257
+ event_hooks=event_hooks,
1258
+ base_url=base_url,
1259
+ transport=transport,
1260
+ trust_env=trust_env,
1261
+ default_encoding=default_encoding,
1262
+ vendor=vendor,
1263
+ product=product,
1264
+ build=build,
1265
+ retry_max=retry_max,
1266
+ json_load_kwargs=json_load_kwargs,
1267
+ json_dump_kwargs=json_dump_kwargs,
1268
+ xml_load_kwargs=xml_load_kwargs,
1269
+ xml_dump_kwargs=xml_dump_kwargs,
1270
+ error_map=error_map,
1271
+ error_class=error_class,
1272
+ )
1273
+
1274
+ async def _deauthenticate(self):
1275
+ """
1276
+ De-authentication stub. De-authentication is automatically run as part
1277
+ of leaving context within the context manager.
1278
+
1279
+ Example:
1280
+ >>> class ExampleAPISession(APISession):
1281
+ ... def _deauthenticate(self):
1282
+ ... self.delete('session/token')
1283
+ """
1284
+
1285
+ async def _request_hook(self, request: Request) -> None:
1286
+ """
1287
+ The Request hook used for debug logging.
1288
+
1289
+ Args:
1290
+ request: The request object.
1291
+ """
1292
+ self._logger.debug(f"REQUESTING {request.method}: {request.url}")
1293
+
1294
+ async def _response_hook(self, response: Response) -> None:
1295
+ """
1296
+ The Response hook used for informational logging.
1297
+
1298
+ Args:
1299
+ response: The response object.
1300
+ """
1301
+ self._logger.info(
1302
+ f"[{response.status_code}] {response.request.method}: {response.request.url}"
1303
+ )
1304
+
1305
+ async def _retry_request(self, response: Response) -> Request:
1306
+ """
1307
+ Processes the request from the response for the purpose of retrying it again.
1308
+
1309
+ Args:
1310
+ response: The response object
1311
+ """
1312
+ return response.request
1313
+
1314
+ @overload
1315
+ async def _request(
1316
+ self,
1317
+ method: HTTPMethods,
1318
+ path: str = "",
1319
+ *,
1320
+ response_model: None = ...,
1321
+ params: QueryParamTypes | None = ...,
1322
+ content: RequestContent | None = ...,
1323
+ data: RequestData | None = ...,
1324
+ files: RequestFiles | None = ...,
1325
+ json: Model | Any | None = ...,
1326
+ xml: XMLModel | str | bytes | None = ...,
1327
+ response_model_kwargs: dict[str, Any] | None = ...,
1328
+ request_model_kwargs: dict[str, Any] | None = ...,
1329
+ headers: dict[str, str] | None = ...,
1330
+ cookies: CookieTypes | None = ...,
1331
+ auth: AuthTypes | UseClientDefault | None = ...,
1332
+ follow_redirects: bool | UseClientDefault = ...,
1333
+ timeout: TimeoutTypes | UseClientDefault = ...,
1334
+ extensions: RequestExtensions | None = ...,
1335
+ max_retries: int | None = ...,
1336
+ error_map: dict[int, ErrorStatus] | None = ...,
1337
+ stream: bool = ...,
1338
+ ) -> Response: ...
1339
+
1340
+ @overload
1341
+ async def _request(
1342
+ self,
1343
+ method: HTTPMethods,
1344
+ path: str = "",
1345
+ *,
1346
+ response_model: type[Model],
1347
+ params: QueryParamTypes | None = ...,
1348
+ content: RequestContent | None = ...,
1349
+ data: RequestData | None = ...,
1350
+ files: RequestFiles | None = ...,
1351
+ json: Model | Any | None = ...,
1352
+ xml: XMLModel | str | bytes | None = ...,
1353
+ response_model_kwargs: dict[str, Any] | None = ...,
1354
+ request_model_kwargs: dict[str, Any] | None = ...,
1355
+ headers: dict[str, str] | None = ...,
1356
+ cookies: CookieTypes | None = ...,
1357
+ auth: AuthTypes | UseClientDefault | None = ...,
1358
+ follow_redirects: bool | UseClientDefault = ...,
1359
+ timeout: TimeoutTypes | UseClientDefault = ...,
1360
+ extensions: RequestExtensions | None = ...,
1361
+ max_retries: int | None = ...,
1362
+ error_map: dict[int, ErrorStatus] | None = ...,
1363
+ stream: bool = False,
1364
+ ) -> Model: ...
1365
+
1366
+ @overload
1367
+ async def _request(
1368
+ self,
1369
+ method: HTTPMethods,
1370
+ path: str = "",
1371
+ *,
1372
+ response_model: type[list[Model]],
1373
+ params: QueryParamTypes | None = ...,
1374
+ content: RequestContent | None = ...,
1375
+ data: RequestData | None = ...,
1376
+ files: RequestFiles | None = ...,
1377
+ json: Model | Any | None = ...,
1378
+ xml: XMLModel | str | bytes | None = ...,
1379
+ response_model_kwargs: dict[str, Any] | None = ...,
1380
+ request_model_kwargs: dict[str, Any] | None = ...,
1381
+ headers: dict[str, str] | None = ...,
1382
+ cookies: CookieTypes | None = ...,
1383
+ auth: AuthTypes | UseClientDefault | None = ...,
1384
+ follow_redirects: bool | UseClientDefault = ...,
1385
+ timeout: TimeoutTypes | UseClientDefault = ...,
1386
+ extensions: RequestExtensions | None = ...,
1387
+ max_retries: int | None = ...,
1388
+ error_map: dict[int, ErrorStatus] | None = ...,
1389
+ stream: bool = False,
1390
+ ) -> list[Model]: ...
1391
+
1392
+ @overload
1393
+ async def _request(
1394
+ self,
1395
+ method: HTTPMethods,
1396
+ path: str = "",
1397
+ *,
1398
+ response_model: type[Model | list[Model]] | None = ...,
1399
+ params: QueryParamTypes | None = ...,
1400
+ content: RequestContent | None = ...,
1401
+ data: RequestData | None = ...,
1402
+ files: RequestFiles | None = ...,
1403
+ json: Model | Any | None = ...,
1404
+ xml: XMLModel | str | bytes | None = ...,
1405
+ response_model_kwargs: dict[str, Any] | None = ...,
1406
+ request_model_kwargs: dict[str, Any] | None = ...,
1407
+ headers: dict[str, str] | None = ...,
1408
+ cookies: CookieTypes | None = ...,
1409
+ auth: AuthTypes | UseClientDefault | None = ...,
1410
+ follow_redirects: bool | UseClientDefault = ...,
1411
+ timeout: TimeoutTypes | UseClientDefault = ...,
1412
+ extensions: RequestExtensions | None = ...,
1413
+ max_retries: int | None = ...,
1414
+ error_map: dict[int, ErrorStatus] | None = ...,
1415
+ stream: bool = ...,
1416
+ ) -> Model | list[Model] | Response: ...
1417
+
1418
+ @override
1419
+ async def _request(
1420
+ self,
1421
+ method: HTTPMethods,
1422
+ path: str = "",
1423
+ *,
1424
+ response_model: type[Model | list[Model]] | None = None,
1425
+ params: QueryParamTypes | None = None,
1426
+ content: RequestContent | None = None,
1427
+ data: RequestData | None = None,
1428
+ files: RequestFiles | None = None,
1429
+ headers: dict[str, str] | None = None,
1430
+ json: Model | Any | None = None,
1431
+ xml: XMLModel | str | bytes | None = None,
1432
+ response_model_kwargs: dict[str, Any] | None = None,
1433
+ request_model_kwargs: dict[str, Any] | None = None,
1434
+ cookies: CookieTypes | None = None,
1435
+ auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
1436
+ follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
1437
+ timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
1438
+ extensions: RequestExtensions | None = None,
1439
+ max_retries: int | None = None,
1440
+ error_map: dict[int, ErrorStatus] | None = None,
1441
+ stream: bool = False,
1442
+ ) -> Model | list[Model] | Response:
1443
+ """
1444
+ Construct and send an HTTP request.
1445
+
1446
+ Args:
1447
+ method:
1448
+ The HTTP method used to make the call.
1449
+ path:
1450
+ URL to query.
1451
+ response_model:
1452
+ Pydantic model to coerce the response into.
1453
+ response_model_kwargs:
1454
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
1455
+ un-marshalling the response data.
1456
+ request_model_kwargs:
1457
+ Keyword arguments to pass to Pydantic/Pydantic-XML as part of
1458
+ marshalling the body of the data into the request.
1459
+ params:
1460
+ Request query parameters.
1461
+ content:
1462
+ Raw body of the request.
1463
+ data:
1464
+ URL form-encoded body for the request.
1465
+ json:
1466
+ Data object to marshal into JSON. Content passed with this parameter
1467
+ will also set the ``Content-Type`` header to ``application/json``.
1468
+ xml:
1469
+ Data object to marshal into XML. Content passed with this parameter
1470
+ will also set the ``Content-Type`` header to ``application/json``.
1471
+ files:
1472
+ A dictionary of upload files to include in the body of the request.
1473
+ headers:
1474
+ Request-specific headers.
1475
+ cookies:
1476
+ Request-specific cookies.
1477
+ auth:
1478
+ Request-specific authentication.
1479
+ follow_redirects:
1480
+ Should the client follow any redirects?
1481
+ timeout:
1482
+ Request-specific timeout settings.
1483
+ extensions:
1484
+ Any additional httpx extensions to pass to the client.
1485
+ max_retries:
1486
+ The maximum number of retries to attempt before giving up. Overloads
1487
+ the client default.
1488
+ error_map:
1489
+ Replaces the client error map with this one instead.
1490
+
1491
+ Returns:
1492
+ Returns the HTTPX Response object if no response_model is specified. If a
1493
+ response_model _is_ specified, then the response will be coerced into the
1494
+ response model and the instance of the model will be returned.
1495
+ """
1496
+ max_retries = max_retries if max_retries else self._retry_max
1497
+ error_map = self._error_map if error_map is None else error_map
1498
+ response_model_kwargs = (
1499
+ {} if response_model_kwargs is None else response_model_kwargs
1500
+ )
1501
+
1502
+ # Perform any pre-processing necessary on the request.
1503
+ kwargs = self._request_pre_process(
1504
+ method=method,
1505
+ url=path,
1506
+ params=params,
1507
+ content=content,
1508
+ data=data,
1509
+ files=files,
1510
+ json=json,
1511
+ xml=xml,
1512
+ headers=headers,
1513
+ cookies=cookies,
1514
+ timeout=timeout,
1515
+ extensions=extensions,
1516
+ request_model_kwargs=request_model_kwargs,
1517
+ )
1518
+
1519
+ # Build the initial request and initialize the counter.
1520
+ request = self._client.build_request(**kwargs)
1521
+ request_counter = 0
1522
+
1523
+ # While the number of requests being performed is less than or equal to the
1524
+ # maximum number allowed, then keep calling the API.
1525
+ while request_counter <= max_retries:
1526
+ request_counter += 1
1527
+ response = await self._client.send(
1528
+ request, auth=auth, follow_redirects=follow_redirects, stream=stream
1529
+ )
1530
+
1531
+ # If the response is ok, then we should return the response. If a model is
1532
+ # presented to us, then we will pass the model to the unmarshal utility to
1533
+ # handle transitioning the data into the expected class.
1534
+ if response.status_code == codes.OK and response_model:
1535
+ return unmarshal(
1536
+ response=response,
1537
+ model=response_model,
1538
+ json_model_kwargs=self._json_load_kwargs | response_model_kwargs,
1539
+ xml_model_kwargs=self._xml_load_kwargs | response_model_kwargs,
1540
+ client=self,
1541
+ )
1542
+
1543
+ # If no model was passed, then simply return the response object.
1544
+ elif response.status_code == codes.OK:
1545
+ return response
1546
+
1547
+ # As the response wasn't ok, let's grab the ErrorStatus object that relates
1548
+ # to the status code that we got and determine the next steps.
1549
+ status = error_map[response.status_code]
1550
+
1551
+ # If the status code is retryable, then pass the response to the retry
1552
+ # handler to perform any optional transformation. Then sleep the amount
1553
+ # if time determined by the status code and then continue to the next
1554
+ # iteration.
1555
+ if status.retry:
1556
+ request = await self._retry_request(response)
1557
+ timer = random.uniform(0, status.jitter) + (
1558
+ request_counter * status.backoff
1559
+ )
1560
+ await sleep(timer)
1561
+ continue
1562
+
1563
+ # Otherwise we will want to raise the error as specified by the error map
1564
+ error_obj = None
1565
+ raise status.exception(
1566
+ response=response, template=status.template, obj=error_obj
1567
+ )
1568
+
1569
+ # If too many attempts were made, then raise a retry error.
1570
+ raise RetryError(url=str(path), method=method, attempts=request_counter)