compass_api_sdk 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of compass_api_sdk might be problematic. Click here for more details.

Files changed (137) hide show
  1. compass_api_sdk/__init__.py +17 -0
  2. compass_api_sdk/_hooks/__init__.py +5 -0
  3. compass_api_sdk/_hooks/registration.py +13 -0
  4. compass_api_sdk/_hooks/sdkhooks.py +76 -0
  5. compass_api_sdk/_hooks/types.py +106 -0
  6. compass_api_sdk/_version.py +15 -0
  7. compass_api_sdk/aave_v3.py +1903 -0
  8. compass_api_sdk/aerodrome_slipstream.py +1875 -0
  9. compass_api_sdk/basesdk.py +362 -0
  10. compass_api_sdk/errors/__init__.py +7 -0
  11. compass_api_sdk/errors/apierror.py +22 -0
  12. compass_api_sdk/errors/httpvalidationerror.py +21 -0
  13. compass_api_sdk/httpclient.py +136 -0
  14. compass_api_sdk/models/__init__.py +777 -0
  15. compass_api_sdk/models/aave_liquidity_changeop.py +108 -0
  16. compass_api_sdk/models/aave_token_priceop.py +98 -0
  17. compass_api_sdk/models/aave_user_position_per_tokenop.py +104 -0
  18. compass_api_sdk/models/aave_user_position_summaryop.py +35 -0
  19. compass_api_sdk/models/aaveborrowrequest.py +105 -0
  20. compass_api_sdk/models/aaveliquiditychangeresponse.py +26 -0
  21. compass_api_sdk/models/aaverepayrequest.py +105 -0
  22. compass_api_sdk/models/aavesupplyrequest.py +93 -0
  23. compass_api_sdk/models/aavetokenpriceresponse.py +15 -0
  24. compass_api_sdk/models/aaveuserpositionpertokenresponse.py +73 -0
  25. compass_api_sdk/models/aaveuserpositionsummaryresponse.py +50 -0
  26. compass_api_sdk/models/aavewithdrawrequest.py +58 -0
  27. compass_api_sdk/models/aerodrome_slipstream_liquidity_provision_positionsop.py +35 -0
  28. compass_api_sdk/models/aerodrome_slipstream_pool_priceop.py +173 -0
  29. compass_api_sdk/models/aerodromelppositionsresponse.py +21 -0
  30. compass_api_sdk/models/aerodromeposition.py +70 -0
  31. compass_api_sdk/models/aerodromeslipstreambuyexactlyrequest.py +92 -0
  32. compass_api_sdk/models/aerodromeslipstreamincreaseliquidityprovisionrequest.py +109 -0
  33. compass_api_sdk/models/aerodromeslipstreammintliquidityprovisionrequest.py +186 -0
  34. compass_api_sdk/models/aerodromeslipstreampoolpriceresponse.py +57 -0
  35. compass_api_sdk/models/aerodromeslipstreamsellexactlyrequest.py +96 -0
  36. compass_api_sdk/models/aerodromeslipstreamwithdrawliquidityprovisionrequest.py +50 -0
  37. compass_api_sdk/models/allowanceinforesponse.py +48 -0
  38. compass_api_sdk/models/balanceinforesponse.py +43 -0
  39. compass_api_sdk/models/chain.py +12 -0
  40. compass_api_sdk/models/chaininfo.py +53 -0
  41. compass_api_sdk/models/compass_api_backend_models_morpho_read_response_get_markets_asset.py +22 -0
  42. compass_api_sdk/models/compass_api_backend_models_morpho_read_response_get_vaults_asset.py +23 -0
  43. compass_api_sdk/models/ensnameinforesponse.py +24 -0
  44. compass_api_sdk/models/feeenum.py +16 -0
  45. compass_api_sdk/models/generic_allowanceop.py +121 -0
  46. compass_api_sdk/models/generic_balanceop.py +104 -0
  47. compass_api_sdk/models/generic_ensop.py +35 -0
  48. compass_api_sdk/models/generic_portfolioop.py +35 -0
  49. compass_api_sdk/models/generic_price_usdop.py +98 -0
  50. compass_api_sdk/models/generic_supported_tokensop.py +29 -0
  51. compass_api_sdk/models/generic_visualize_portfolioop.py +35 -0
  52. compass_api_sdk/models/image.py +15 -0
  53. compass_api_sdk/models/increaseallowancerequest.py +77 -0
  54. compass_api_sdk/models/interestratemode.py +14 -0
  55. compass_api_sdk/models/marketstate.py +35 -0
  56. compass_api_sdk/models/morpho_market_positionop.py +39 -0
  57. compass_api_sdk/models/morpho_marketsop.py +78 -0
  58. compass_api_sdk/models/morpho_vault_positionop.py +39 -0
  59. compass_api_sdk/models/morpho_vaultsop.py +72 -0
  60. compass_api_sdk/models/morphoborrowrequest.py +91 -0
  61. compass_api_sdk/models/morphocheckmarketpositionresponse.py +23 -0
  62. compass_api_sdk/models/morphocheckvaultpositionresponse.py +20 -0
  63. compass_api_sdk/models/morphodepositrequest.py +86 -0
  64. compass_api_sdk/models/morphogetmarketsresponse.py +17 -0
  65. compass_api_sdk/models/morphogetvaultsresponse.py +17 -0
  66. compass_api_sdk/models/morphomarket.py +80 -0
  67. compass_api_sdk/models/morphorepayrequest.py +79 -0
  68. compass_api_sdk/models/morphosetvaultallowancerequest.py +44 -0
  69. compass_api_sdk/models/morphosupplycollateralrequest.py +91 -0
  70. compass_api_sdk/models/morphovault.py +47 -0
  71. compass_api_sdk/models/morphowithdrawcollateralrequest.py +91 -0
  72. compass_api_sdk/models/morphowithdrawrequest.py +74 -0
  73. compass_api_sdk/models/portfolio.py +22 -0
  74. compass_api_sdk/models/priceresponse.py +15 -0
  75. compass_api_sdk/models/security.py +24 -0
  76. compass_api_sdk/models/token_addressop.py +98 -0
  77. compass_api_sdk/models/token_balanceop.py +49 -0
  78. compass_api_sdk/models/token_enum.py +57 -0
  79. compass_api_sdk/models/token_priceop.py +97 -0
  80. compass_api_sdk/models/tokenaddressresponse.py +15 -0
  81. compass_api_sdk/models/tokenbalance.py +49 -0
  82. compass_api_sdk/models/tokenbalanceresponse.py +44 -0
  83. compass_api_sdk/models/tokeninfo.py +17 -0
  84. compass_api_sdk/models/tokenpriceresponse.py +15 -0
  85. compass_api_sdk/models/tokentransferrequest.py +66 -0
  86. compass_api_sdk/models/transfererc20request.py +62 -0
  87. compass_api_sdk/models/transferethrequest.py +46 -0
  88. compass_api_sdk/models/uniswap_liquidity_provision_in_rangeop.py +34 -0
  89. compass_api_sdk/models/uniswap_liquidity_provision_positionsop.py +35 -0
  90. compass_api_sdk/models/uniswap_pool_priceop.py +193 -0
  91. compass_api_sdk/models/uniswap_quote_buy_exactlyop.py +209 -0
  92. compass_api_sdk/models/uniswap_quote_sell_exactlyop.py +209 -0
  93. compass_api_sdk/models/uniswapbuyexactlyrequest.py +104 -0
  94. compass_api_sdk/models/uniswapbuyquoteinforesponse.py +20 -0
  95. compass_api_sdk/models/uniswapcheckinrangeresponse.py +15 -0
  96. compass_api_sdk/models/uniswapincreaseliquidityprovisionrequest.py +99 -0
  97. compass_api_sdk/models/uniswaplppositionsinforesponse.py +24 -0
  98. compass_api_sdk/models/uniswapmintliquidityprovisionrequest.py +185 -0
  99. compass_api_sdk/models/uniswappoolpriceresponse.py +47 -0
  100. compass_api_sdk/models/uniswappositionssolidityresponse.py +46 -0
  101. compass_api_sdk/models/uniswapsellexactlyrequest.py +104 -0
  102. compass_api_sdk/models/uniswapsellquoteinforesponse.py +20 -0
  103. compass_api_sdk/models/uniswapwithdrawliquidityprovisionrequest.py +51 -0
  104. compass_api_sdk/models/unsignedtransaction.py +58 -0
  105. compass_api_sdk/models/unwrapwethrequest.py +41 -0
  106. compass_api_sdk/models/validationerror.py +26 -0
  107. compass_api_sdk/models/vaultstate.py +32 -0
  108. compass_api_sdk/models/weeklyapys.py +23 -0
  109. compass_api_sdk/models/wrapethrequest.py +41 -0
  110. compass_api_sdk/morpho.py +2577 -0
  111. compass_api_sdk/py.typed +1 -0
  112. compass_api_sdk/sdk.py +155 -0
  113. compass_api_sdk/sdkconfiguration.py +56 -0
  114. compass_api_sdk/token_sdk.py +861 -0
  115. compass_api_sdk/types/__init__.py +21 -0
  116. compass_api_sdk/types/basemodel.py +39 -0
  117. compass_api_sdk/uniswap_v3.py +2551 -0
  118. compass_api_sdk/universal.py +2625 -0
  119. compass_api_sdk/utils/__init__.py +100 -0
  120. compass_api_sdk/utils/annotations.py +55 -0
  121. compass_api_sdk/utils/datetimes.py +23 -0
  122. compass_api_sdk/utils/enums.py +74 -0
  123. compass_api_sdk/utils/eventstreaming.py +238 -0
  124. compass_api_sdk/utils/forms.py +202 -0
  125. compass_api_sdk/utils/headers.py +136 -0
  126. compass_api_sdk/utils/logger.py +22 -0
  127. compass_api_sdk/utils/metadata.py +118 -0
  128. compass_api_sdk/utils/queryparams.py +205 -0
  129. compass_api_sdk/utils/requestbodies.py +66 -0
  130. compass_api_sdk/utils/retries.py +217 -0
  131. compass_api_sdk/utils/security.py +174 -0
  132. compass_api_sdk/utils/serializers.py +248 -0
  133. compass_api_sdk/utils/url.py +155 -0
  134. compass_api_sdk/utils/values.py +137 -0
  135. compass_api_sdk-0.0.1.dist-info/METADATA +534 -0
  136. compass_api_sdk-0.0.1.dist-info/RECORD +137 -0
  137. compass_api_sdk-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,362 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from .sdkconfiguration import SDKConfiguration
4
+ from compass_api_sdk import errors, utils
5
+ from compass_api_sdk._hooks import (
6
+ AfterErrorContext,
7
+ AfterSuccessContext,
8
+ BeforeRequestContext,
9
+ )
10
+ from compass_api_sdk.utils import RetryConfig, SerializedRequestBody, get_body_content
11
+ import httpx
12
+ from typing import Callable, List, Mapping, Optional, Tuple
13
+ from urllib.parse import parse_qs, urlparse
14
+
15
+
16
+ class BaseSDK:
17
+ sdk_configuration: SDKConfiguration
18
+
19
+ def __init__(self, sdk_config: SDKConfiguration) -> None:
20
+ self.sdk_configuration = sdk_config
21
+
22
+ def _get_url(self, base_url, url_variables):
23
+ sdk_url, sdk_variables = self.sdk_configuration.get_server_details()
24
+
25
+ if base_url is None:
26
+ base_url = sdk_url
27
+
28
+ if url_variables is None:
29
+ url_variables = sdk_variables
30
+
31
+ return utils.template_url(base_url, url_variables)
32
+
33
+ def _build_request_async(
34
+ self,
35
+ method,
36
+ path,
37
+ base_url,
38
+ url_variables,
39
+ request,
40
+ request_body_required,
41
+ request_has_path_params,
42
+ request_has_query_params,
43
+ user_agent_header,
44
+ accept_header_value,
45
+ _globals=None,
46
+ security=None,
47
+ timeout_ms: Optional[int] = None,
48
+ get_serialized_body: Optional[
49
+ Callable[[], Optional[SerializedRequestBody]]
50
+ ] = None,
51
+ url_override: Optional[str] = None,
52
+ http_headers: Optional[Mapping[str, str]] = None,
53
+ ) -> httpx.Request:
54
+ client = self.sdk_configuration.async_client
55
+ return self._build_request_with_client(
56
+ client,
57
+ method,
58
+ path,
59
+ base_url,
60
+ url_variables,
61
+ request,
62
+ request_body_required,
63
+ request_has_path_params,
64
+ request_has_query_params,
65
+ user_agent_header,
66
+ accept_header_value,
67
+ _globals,
68
+ security,
69
+ timeout_ms,
70
+ get_serialized_body,
71
+ url_override,
72
+ http_headers,
73
+ )
74
+
75
+ def _build_request(
76
+ self,
77
+ method,
78
+ path,
79
+ base_url,
80
+ url_variables,
81
+ request,
82
+ request_body_required,
83
+ request_has_path_params,
84
+ request_has_query_params,
85
+ user_agent_header,
86
+ accept_header_value,
87
+ _globals=None,
88
+ security=None,
89
+ timeout_ms: Optional[int] = None,
90
+ get_serialized_body: Optional[
91
+ Callable[[], Optional[SerializedRequestBody]]
92
+ ] = None,
93
+ url_override: Optional[str] = None,
94
+ http_headers: Optional[Mapping[str, str]] = None,
95
+ ) -> httpx.Request:
96
+ client = self.sdk_configuration.client
97
+ return self._build_request_with_client(
98
+ client,
99
+ method,
100
+ path,
101
+ base_url,
102
+ url_variables,
103
+ request,
104
+ request_body_required,
105
+ request_has_path_params,
106
+ request_has_query_params,
107
+ user_agent_header,
108
+ accept_header_value,
109
+ _globals,
110
+ security,
111
+ timeout_ms,
112
+ get_serialized_body,
113
+ url_override,
114
+ http_headers,
115
+ )
116
+
117
+ def _build_request_with_client(
118
+ self,
119
+ client,
120
+ method,
121
+ path,
122
+ base_url,
123
+ url_variables,
124
+ request,
125
+ request_body_required,
126
+ request_has_path_params,
127
+ request_has_query_params,
128
+ user_agent_header,
129
+ accept_header_value,
130
+ _globals=None,
131
+ security=None,
132
+ timeout_ms: Optional[int] = None,
133
+ get_serialized_body: Optional[
134
+ Callable[[], Optional[SerializedRequestBody]]
135
+ ] = None,
136
+ url_override: Optional[str] = None,
137
+ http_headers: Optional[Mapping[str, str]] = None,
138
+ ) -> httpx.Request:
139
+ query_params = {}
140
+
141
+ url = url_override
142
+ if url is None:
143
+ url = utils.generate_url(
144
+ self._get_url(base_url, url_variables),
145
+ path,
146
+ request if request_has_path_params else None,
147
+ _globals if request_has_path_params else None,
148
+ )
149
+
150
+ query_params = utils.get_query_params(
151
+ request if request_has_query_params else None,
152
+ _globals if request_has_query_params else None,
153
+ )
154
+ else:
155
+ # Pick up the query parameter from the override so they can be
156
+ # preserved when building the request later on (necessary as of
157
+ # httpx 0.28).
158
+ parsed_override = urlparse(str(url_override))
159
+ query_params = parse_qs(parsed_override.query, keep_blank_values=True)
160
+
161
+ headers = utils.get_headers(request, _globals)
162
+ headers["Accept"] = accept_header_value
163
+ headers[user_agent_header] = self.sdk_configuration.user_agent
164
+
165
+ if security is not None:
166
+ if callable(security):
167
+ security = security()
168
+
169
+ if security is not None:
170
+ security_headers, security_query_params = utils.get_security(security)
171
+ headers = {**headers, **security_headers}
172
+ query_params = {**query_params, **security_query_params}
173
+
174
+ serialized_request_body = SerializedRequestBody()
175
+ if get_serialized_body is not None:
176
+ rb = get_serialized_body()
177
+ if request_body_required and rb is None:
178
+ raise ValueError("request body is required")
179
+
180
+ if rb is not None:
181
+ serialized_request_body = rb
182
+
183
+ if (
184
+ serialized_request_body.media_type is not None
185
+ and serialized_request_body.media_type
186
+ not in (
187
+ "multipart/form-data",
188
+ "multipart/mixed",
189
+ )
190
+ ):
191
+ headers["content-type"] = serialized_request_body.media_type
192
+
193
+ if http_headers is not None:
194
+ for header, value in http_headers.items():
195
+ headers[header] = value
196
+
197
+ timeout = timeout_ms / 1000 if timeout_ms is not None else None
198
+
199
+ return client.build_request(
200
+ method,
201
+ url,
202
+ params=query_params,
203
+ content=serialized_request_body.content,
204
+ data=serialized_request_body.data,
205
+ files=serialized_request_body.files,
206
+ headers=headers,
207
+ timeout=timeout,
208
+ )
209
+
210
+ def do_request(
211
+ self,
212
+ hook_ctx,
213
+ request,
214
+ error_status_codes,
215
+ stream=False,
216
+ retry_config: Optional[Tuple[RetryConfig, List[str]]] = None,
217
+ ) -> httpx.Response:
218
+ client = self.sdk_configuration.client
219
+ logger = self.sdk_configuration.debug_logger
220
+
221
+ def do():
222
+ http_res = None
223
+ try:
224
+ req = self.sdk_configuration.get_hooks().before_request(
225
+ BeforeRequestContext(hook_ctx), request
226
+ )
227
+ logger.debug(
228
+ "Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
229
+ req.method,
230
+ req.url,
231
+ req.headers,
232
+ get_body_content(req),
233
+ )
234
+
235
+ if client is None:
236
+ raise ValueError("client is required")
237
+
238
+ http_res = client.send(req, stream=stream)
239
+ except Exception as e:
240
+ _, e = self.sdk_configuration.get_hooks().after_error(
241
+ AfterErrorContext(hook_ctx), None, e
242
+ )
243
+ if e is not None:
244
+ logger.debug("Request Exception", exc_info=True)
245
+ raise e
246
+
247
+ if http_res is None:
248
+ logger.debug("Raising no response SDK error")
249
+ raise errors.APIError("No response received")
250
+
251
+ logger.debug(
252
+ "Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
253
+ http_res.status_code,
254
+ http_res.url,
255
+ http_res.headers,
256
+ "<streaming response>" if stream else http_res.text,
257
+ )
258
+
259
+ if utils.match_status_codes(error_status_codes, http_res.status_code):
260
+ result, err = self.sdk_configuration.get_hooks().after_error(
261
+ AfterErrorContext(hook_ctx), http_res, None
262
+ )
263
+ if err is not None:
264
+ logger.debug("Request Exception", exc_info=True)
265
+ raise err
266
+ if result is not None:
267
+ http_res = result
268
+ else:
269
+ logger.debug("Raising unexpected SDK error")
270
+ raise errors.APIError("Unexpected error occurred")
271
+
272
+ return http_res
273
+
274
+ if retry_config is not None:
275
+ http_res = utils.retry(do, utils.Retries(retry_config[0], retry_config[1]))
276
+ else:
277
+ http_res = do()
278
+
279
+ if not utils.match_status_codes(error_status_codes, http_res.status_code):
280
+ http_res = self.sdk_configuration.get_hooks().after_success(
281
+ AfterSuccessContext(hook_ctx), http_res
282
+ )
283
+
284
+ return http_res
285
+
286
+ async def do_request_async(
287
+ self,
288
+ hook_ctx,
289
+ request,
290
+ error_status_codes,
291
+ stream=False,
292
+ retry_config: Optional[Tuple[RetryConfig, List[str]]] = None,
293
+ ) -> httpx.Response:
294
+ client = self.sdk_configuration.async_client
295
+ logger = self.sdk_configuration.debug_logger
296
+
297
+ async def do():
298
+ http_res = None
299
+ try:
300
+ req = self.sdk_configuration.get_hooks().before_request(
301
+ BeforeRequestContext(hook_ctx), request
302
+ )
303
+ logger.debug(
304
+ "Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
305
+ req.method,
306
+ req.url,
307
+ req.headers,
308
+ get_body_content(req),
309
+ )
310
+
311
+ if client is None:
312
+ raise ValueError("client is required")
313
+
314
+ http_res = await client.send(req, stream=stream)
315
+ except Exception as e:
316
+ _, e = self.sdk_configuration.get_hooks().after_error(
317
+ AfterErrorContext(hook_ctx), None, e
318
+ )
319
+ if e is not None:
320
+ logger.debug("Request Exception", exc_info=True)
321
+ raise e
322
+
323
+ if http_res is None:
324
+ logger.debug("Raising no response SDK error")
325
+ raise errors.APIError("No response received")
326
+
327
+ logger.debug(
328
+ "Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
329
+ http_res.status_code,
330
+ http_res.url,
331
+ http_res.headers,
332
+ "<streaming response>" if stream else http_res.text,
333
+ )
334
+
335
+ if utils.match_status_codes(error_status_codes, http_res.status_code):
336
+ result, err = self.sdk_configuration.get_hooks().after_error(
337
+ AfterErrorContext(hook_ctx), http_res, None
338
+ )
339
+ if err is not None:
340
+ logger.debug("Request Exception", exc_info=True)
341
+ raise err
342
+ if result is not None:
343
+ http_res = result
344
+ else:
345
+ logger.debug("Raising unexpected SDK error")
346
+ raise errors.APIError("Unexpected error occurred")
347
+
348
+ return http_res
349
+
350
+ if retry_config is not None:
351
+ http_res = await utils.retry_async(
352
+ do, utils.Retries(retry_config[0], retry_config[1])
353
+ )
354
+ else:
355
+ http_res = await do()
356
+
357
+ if not utils.match_status_codes(error_status_codes, http_res.status_code):
358
+ http_res = self.sdk_configuration.get_hooks().after_success(
359
+ AfterSuccessContext(hook_ctx), http_res
360
+ )
361
+
362
+ return http_res
@@ -0,0 +1,7 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from .apierror import APIError
4
+ from .httpvalidationerror import HTTPValidationError, HTTPValidationErrorData
5
+
6
+
7
+ __all__ = ["APIError", "HTTPValidationError", "HTTPValidationErrorData"]
@@ -0,0 +1,22 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Optional
5
+ import httpx
6
+
7
+
8
+ @dataclass
9
+ class APIError(Exception):
10
+ """Represents an error returned by the API."""
11
+
12
+ message: str
13
+ status_code: int = -1
14
+ body: str = ""
15
+ raw_response: Optional[httpx.Response] = None
16
+
17
+ def __str__(self):
18
+ body = ""
19
+ if len(self.body) > 0:
20
+ body = f"\n{self.body}"
21
+
22
+ return f"{self.message}: Status {self.status_code}{body}"
@@ -0,0 +1,21 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from compass_api_sdk import utils
5
+ from compass_api_sdk.models import validationerror as models_validationerror
6
+ from compass_api_sdk.types import BaseModel
7
+ from typing import List, Optional
8
+
9
+
10
+ class HTTPValidationErrorData(BaseModel):
11
+ detail: Optional[List[models_validationerror.ValidationError]] = None
12
+
13
+
14
+ class HTTPValidationError(Exception):
15
+ data: HTTPValidationErrorData
16
+
17
+ def __init__(self, data: HTTPValidationErrorData):
18
+ self.data = data
19
+
20
+ def __str__(self) -> str:
21
+ return utils.marshal_json(self.data, HTTPValidationErrorData)
@@ -0,0 +1,136 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ # pyright: reportReturnType = false
4
+ import asyncio
5
+ from concurrent.futures import ThreadPoolExecutor
6
+ from typing_extensions import Protocol, runtime_checkable
7
+ import httpx
8
+ from typing import Any, Optional, Union
9
+
10
+
11
+ @runtime_checkable
12
+ class HttpClient(Protocol):
13
+ def send(
14
+ self,
15
+ request: httpx.Request,
16
+ *,
17
+ stream: bool = False,
18
+ auth: Union[
19
+ httpx._types.AuthTypes, httpx._client.UseClientDefault, None
20
+ ] = httpx.USE_CLIENT_DEFAULT,
21
+ follow_redirects: Union[
22
+ bool, httpx._client.UseClientDefault
23
+ ] = httpx.USE_CLIENT_DEFAULT,
24
+ ) -> httpx.Response:
25
+ pass
26
+
27
+ def build_request(
28
+ self,
29
+ method: str,
30
+ url: httpx._types.URLTypes,
31
+ *,
32
+ content: Optional[httpx._types.RequestContent] = None,
33
+ data: Optional[httpx._types.RequestData] = None,
34
+ files: Optional[httpx._types.RequestFiles] = None,
35
+ json: Optional[Any] = None,
36
+ params: Optional[httpx._types.QueryParamTypes] = None,
37
+ headers: Optional[httpx._types.HeaderTypes] = None,
38
+ cookies: Optional[httpx._types.CookieTypes] = None,
39
+ timeout: Union[
40
+ httpx._types.TimeoutTypes, httpx._client.UseClientDefault
41
+ ] = httpx.USE_CLIENT_DEFAULT,
42
+ extensions: Optional[httpx._types.RequestExtensions] = None,
43
+ ) -> httpx.Request:
44
+ pass
45
+
46
+ def close(self) -> None:
47
+ pass
48
+
49
+
50
+ @runtime_checkable
51
+ class AsyncHttpClient(Protocol):
52
+ async def send(
53
+ self,
54
+ request: httpx.Request,
55
+ *,
56
+ stream: bool = False,
57
+ auth: Union[
58
+ httpx._types.AuthTypes, httpx._client.UseClientDefault, None
59
+ ] = httpx.USE_CLIENT_DEFAULT,
60
+ follow_redirects: Union[
61
+ bool, httpx._client.UseClientDefault
62
+ ] = httpx.USE_CLIENT_DEFAULT,
63
+ ) -> httpx.Response:
64
+ pass
65
+
66
+ def build_request(
67
+ self,
68
+ method: str,
69
+ url: httpx._types.URLTypes,
70
+ *,
71
+ content: Optional[httpx._types.RequestContent] = None,
72
+ data: Optional[httpx._types.RequestData] = None,
73
+ files: Optional[httpx._types.RequestFiles] = None,
74
+ json: Optional[Any] = None,
75
+ params: Optional[httpx._types.QueryParamTypes] = None,
76
+ headers: Optional[httpx._types.HeaderTypes] = None,
77
+ cookies: Optional[httpx._types.CookieTypes] = None,
78
+ timeout: Union[
79
+ httpx._types.TimeoutTypes, httpx._client.UseClientDefault
80
+ ] = httpx.USE_CLIENT_DEFAULT,
81
+ extensions: Optional[httpx._types.RequestExtensions] = None,
82
+ ) -> httpx.Request:
83
+ pass
84
+
85
+ async def aclose(self) -> None:
86
+ pass
87
+
88
+
89
+ class ClientOwner(Protocol):
90
+ client: Union[HttpClient, None]
91
+ async_client: Union[AsyncHttpClient, None]
92
+
93
+
94
+ def close_clients(
95
+ owner: ClientOwner,
96
+ sync_client: Union[HttpClient, None],
97
+ sync_client_supplied: bool,
98
+ async_client: Union[AsyncHttpClient, None],
99
+ async_client_supplied: bool,
100
+ ) -> None:
101
+ """
102
+ A finalizer function that is meant to be used with weakref.finalize to close
103
+ httpx clients used by an SDK so that underlying resources can be garbage
104
+ collected.
105
+ """
106
+
107
+ # Unset the client/async_client properties so there are no more references
108
+ # to them from the owning SDK instance and they can be reaped.
109
+ owner.client = None
110
+ owner.async_client = None
111
+
112
+ if sync_client is not None and not sync_client_supplied:
113
+ try:
114
+ sync_client.close()
115
+ except Exception:
116
+ pass
117
+
118
+ if async_client is not None and not async_client_supplied:
119
+ is_async = False
120
+ try:
121
+ asyncio.get_running_loop()
122
+ is_async = True
123
+ except RuntimeError:
124
+ pass
125
+
126
+ try:
127
+ # If this function is called in an async loop then start another
128
+ # loop in a separate thread to close the async http client.
129
+ if is_async:
130
+ with ThreadPoolExecutor(max_workers=1) as executor:
131
+ future = executor.submit(asyncio.run, async_client.aclose())
132
+ future.result()
133
+ else:
134
+ asyncio.run(async_client.aclose())
135
+ except Exception:
136
+ pass