swpreq 0.1.0__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.
- swpreq/__init__.py +80 -0
- swpreq/_native.py +334 -0
- swpreq/async_api.py +74 -0
- swpreq/client.py +401 -0
- swpreq/exceptions.py +73 -0
- swpreq/hooks.py +29 -0
- swpreq/lib/android-arm64/libswpreq.so +0 -0
- swpreq/lib/android-armv7/libswpreq.so +0 -0
- swpreq/lib/android-x64/libswpreq.so +0 -0
- swpreq/lib/android-x86/libswpreq.so +0 -0
- swpreq/lib/linux-arm64/libswpreq.so +0 -0
- swpreq/lib/linux-armv7/libswpreq.so +0 -0
- swpreq/lib/linux-x64/libswpreq.so +0 -0
- swpreq/lib/macos-arm64/libswpreq.dylib +0 -0
- swpreq/lib/macos-x64/libswpreq.dylib +0 -0
- swpreq/lib/windows-arm64/swpreq.dll +0 -0
- swpreq/lib/windows-x64/swpreq.dll +0 -0
- swpreq/lib/windows-x86/swpreq.dll +0 -0
- swpreq/multipart.py +83 -0
- swpreq/oauth.py +142 -0
- swpreq/response.py +128 -0
- swpreq/retry.py +43 -0
- swpreq/sse.py +99 -0
- swpreq/streaming.py +55 -0
- swpreq/sync_api.py +44 -0
- swpreq/websocket.py +288 -0
- swpreq-0.1.0.dist-info/METADATA +1346 -0
- swpreq-0.1.0.dist-info/RECORD +31 -0
- swpreq-0.1.0.dist-info/WHEEL +5 -0
- swpreq-0.1.0.dist-info/licenses/LICENSE +21 -0
- swpreq-0.1.0.dist-info/top_level.txt +1 -0
swpreq/__init__.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from ._native import get_lib, get_platform_info, detect_platform
|
|
2
|
+
from .client import Client, Session
|
|
3
|
+
from .response import Response
|
|
4
|
+
from .exceptions import (
|
|
5
|
+
SwpreqError,
|
|
6
|
+
PlatformNotSupportedError,
|
|
7
|
+
CoreLoadError,
|
|
8
|
+
FileLockedError,
|
|
9
|
+
NetworkError,
|
|
10
|
+
TimeoutError,
|
|
11
|
+
InvalidUrlError,
|
|
12
|
+
TlsError,
|
|
13
|
+
ProxyError,
|
|
14
|
+
DecodeError,
|
|
15
|
+
EncodeError,
|
|
16
|
+
NotFoundError,
|
|
17
|
+
HTTPError,
|
|
18
|
+
)
|
|
19
|
+
from .sync_api import get, post, put, delete, patch, head, options, request
|
|
20
|
+
from .streaming import ResponseStream
|
|
21
|
+
from .sse import SseStream, SseEvent
|
|
22
|
+
from .multipart import MultipartBuilder
|
|
23
|
+
from .retry import RetryPolicy
|
|
24
|
+
from .oauth import OAuth1, OAuth1Params, OAuth2
|
|
25
|
+
from .websocket import WebSocket, AsyncWebSocket, WebSocketMessage
|
|
26
|
+
|
|
27
|
+
__version__ = "0.1.0"
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"Client",
|
|
31
|
+
"Session",
|
|
32
|
+
"Response",
|
|
33
|
+
"ResponseStream",
|
|
34
|
+
"SseStream",
|
|
35
|
+
"SseEvent",
|
|
36
|
+
"MultipartBuilder",
|
|
37
|
+
"RetryPolicy",
|
|
38
|
+
"OAuth1",
|
|
39
|
+
"OAuth1Params",
|
|
40
|
+
"OAuth2",
|
|
41
|
+
"WebSocket",
|
|
42
|
+
"AsyncWebSocket",
|
|
43
|
+
"WebSocketMessage",
|
|
44
|
+
"SwpreqError",
|
|
45
|
+
"PlatformNotSupportedError",
|
|
46
|
+
"CoreLoadError",
|
|
47
|
+
"FileLockedError",
|
|
48
|
+
"NetworkError",
|
|
49
|
+
"TimeoutError",
|
|
50
|
+
"InvalidUrlError",
|
|
51
|
+
"TlsError",
|
|
52
|
+
"ProxyError",
|
|
53
|
+
"DecodeError",
|
|
54
|
+
"EncodeError",
|
|
55
|
+
"NotFoundError",
|
|
56
|
+
"HTTPError",
|
|
57
|
+
"get",
|
|
58
|
+
"post",
|
|
59
|
+
"put",
|
|
60
|
+
"delete",
|
|
61
|
+
"patch",
|
|
62
|
+
"head",
|
|
63
|
+
"options",
|
|
64
|
+
"request",
|
|
65
|
+
"get_lib",
|
|
66
|
+
"get_platform_info",
|
|
67
|
+
"detect_platform",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def __getattr__(name):
|
|
72
|
+
if name == "AsyncClient":
|
|
73
|
+
from .async_api import AsyncClient
|
|
74
|
+
|
|
75
|
+
return AsyncClient
|
|
76
|
+
if name == "AsyncSession":
|
|
77
|
+
from .async_api import AsyncSession
|
|
78
|
+
|
|
79
|
+
return AsyncSession
|
|
80
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
swpreq/_native.py
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import ctypes.util
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import platform
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import tempfile
|
|
10
|
+
import threading
|
|
11
|
+
import time
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
from .exceptions import (
|
|
16
|
+
PlatformNotSupportedError,
|
|
17
|
+
CoreLoadError,
|
|
18
|
+
FileLockedError,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SUPPORTED_PLATFORMS = {
|
|
23
|
+
("windows", "x64"): "swpreq.dll",
|
|
24
|
+
("windows", "arm64"): "swpreq.dll",
|
|
25
|
+
("linux", "x64"): "libswpreq.so",
|
|
26
|
+
("linux", "arm64"): "libswpreq.so",
|
|
27
|
+
("linux", "armv7"): "libswpreq.so",
|
|
28
|
+
("macos", "x64"): "libswpreq.dylib",
|
|
29
|
+
("macos", "arm64"): "libswpreq.dylib",
|
|
30
|
+
("android", "arm64"): "libswpreq.so",
|
|
31
|
+
("android", "armv7"): "libswpreq.so",
|
|
32
|
+
("android", "x64"): "libswpreq.so",
|
|
33
|
+
("android", "x86"): "libswpreq.so",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _detect_android() -> bool:
|
|
38
|
+
if "ANDROID_ROOT" in os.environ:
|
|
39
|
+
return True
|
|
40
|
+
if "ANDROID_DATA" in os.environ:
|
|
41
|
+
return True
|
|
42
|
+
if os.path.exists("/system/build.prop"):
|
|
43
|
+
return True
|
|
44
|
+
try:
|
|
45
|
+
return "android" in platform.platform().lower()
|
|
46
|
+
except Exception:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _detect_macos_arch() -> str:
|
|
51
|
+
machine = platform.machine().lower()
|
|
52
|
+
if machine in ("x86_64", "amd64"):
|
|
53
|
+
try:
|
|
54
|
+
result = subprocess.run(
|
|
55
|
+
["sysctl", "-n", "sysctl.proc_translated"],
|
|
56
|
+
capture_output=True,
|
|
57
|
+
text=True,
|
|
58
|
+
timeout=1,
|
|
59
|
+
)
|
|
60
|
+
if result.returncode == 0 and result.stdout.strip() == "1":
|
|
61
|
+
return "arm64"
|
|
62
|
+
except Exception:
|
|
63
|
+
pass
|
|
64
|
+
return machine
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def detect_platform() -> tuple:
|
|
68
|
+
system = platform.system().lower()
|
|
69
|
+
machine = platform.machine().lower()
|
|
70
|
+
|
|
71
|
+
if system == "windows":
|
|
72
|
+
os_name = "windows"
|
|
73
|
+
elif system == "darwin":
|
|
74
|
+
os_name = "macos"
|
|
75
|
+
machine = _detect_macos_arch()
|
|
76
|
+
elif system == "linux":
|
|
77
|
+
os_name = "android" if _detect_android() else "linux"
|
|
78
|
+
else:
|
|
79
|
+
os_name = system
|
|
80
|
+
|
|
81
|
+
if machine in ("x86_64", "amd64"):
|
|
82
|
+
arch = "x64"
|
|
83
|
+
elif machine in ("aarch64", "arm64"):
|
|
84
|
+
arch = "arm64"
|
|
85
|
+
elif machine in ("armv7l", "armv6l", "armv8l"):
|
|
86
|
+
arch = "armv7"
|
|
87
|
+
elif machine in ("i386", "i686", "x86"):
|
|
88
|
+
arch = "x86"
|
|
89
|
+
else:
|
|
90
|
+
arch = machine
|
|
91
|
+
|
|
92
|
+
return os_name, arch
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def find_library() -> str:
|
|
96
|
+
os_name, arch = detect_platform()
|
|
97
|
+
key = (os_name, arch)
|
|
98
|
+
|
|
99
|
+
if key not in SUPPORTED_PLATFORMS:
|
|
100
|
+
supported = ", ".join(f"{o}-{a}" for o, a in sorted(SUPPORTED_PLATFORMS))
|
|
101
|
+
raise PlatformNotSupportedError(
|
|
102
|
+
f"Platform '{os_name}-{arch}' is not supported.\n"
|
|
103
|
+
f"Supported: {supported}"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
lib_name = SUPPORTED_PLATFORMS[key]
|
|
107
|
+
pkg_dir = Path(__file__).parent
|
|
108
|
+
|
|
109
|
+
candidates = [
|
|
110
|
+
pkg_dir / "lib" / f"{os_name}-{arch}" / lib_name,
|
|
111
|
+
pkg_dir / lib_name,
|
|
112
|
+
pkg_dir.parent.parent / "target" / "release" / lib_name,
|
|
113
|
+
pkg_dir.parent.parent / "target" / "debug" / lib_name,
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
for c in candidates:
|
|
117
|
+
if c.exists():
|
|
118
|
+
return str(c)
|
|
119
|
+
|
|
120
|
+
tried = "\n".join(f" - {c}" for c in candidates)
|
|
121
|
+
raise CoreLoadError(
|
|
122
|
+
f"Binary not found for {os_name}-{arch}.\n"
|
|
123
|
+
f"Expected: {lib_name}\n"
|
|
124
|
+
f"Tried:\n{tried}"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class SwpreqResponse(ctypes.Structure):
|
|
129
|
+
_fields_ = [
|
|
130
|
+
("status_code", ctypes.c_uint16),
|
|
131
|
+
("_pad", ctypes.c_uint16),
|
|
132
|
+
("body", ctypes.POINTER(ctypes.c_uint8)),
|
|
133
|
+
("body_len", ctypes.c_size_t),
|
|
134
|
+
("headers_json", ctypes.c_char_p),
|
|
135
|
+
("url", ctypes.c_char_p),
|
|
136
|
+
("error", ctypes.c_char_p),
|
|
137
|
+
("elapsed_ms", ctypes.c_uint64),
|
|
138
|
+
("http_version", ctypes.c_uint32),
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
ON_MESSAGE_CB = ctypes.CFUNCTYPE(
|
|
143
|
+
None,
|
|
144
|
+
ctypes.c_void_p,
|
|
145
|
+
ctypes.c_int,
|
|
146
|
+
ctypes.POINTER(ctypes.c_uint8),
|
|
147
|
+
ctypes.c_size_t,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
ON_EVENT_CB = ctypes.CFUNCTYPE(
|
|
151
|
+
None,
|
|
152
|
+
ctypes.c_void_p,
|
|
153
|
+
ctypes.c_int,
|
|
154
|
+
ctypes.c_char_p,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class CoreLib:
|
|
159
|
+
_instance = None
|
|
160
|
+
_lock = threading.Lock()
|
|
161
|
+
|
|
162
|
+
def __new__(cls):
|
|
163
|
+
if cls._instance is None:
|
|
164
|
+
with cls._lock:
|
|
165
|
+
if cls._instance is None:
|
|
166
|
+
cls._instance = super().__new__(cls)
|
|
167
|
+
cls._instance._load()
|
|
168
|
+
return cls._instance
|
|
169
|
+
|
|
170
|
+
def __getattr__(self, name):
|
|
171
|
+
# Delegate unknown attributes to the raw CDLL
|
|
172
|
+
# so that client.py can call lib.swpreq_client_new() etc.
|
|
173
|
+
lib = self.__dict__.get("lib")
|
|
174
|
+
if lib is not None:
|
|
175
|
+
return getattr(lib, name)
|
|
176
|
+
raise AttributeError(f"CoreLib has no attribute '{name}'")
|
|
177
|
+
|
|
178
|
+
def _load(self) -> None:
|
|
179
|
+
lib_path = find_library()
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
self.lib = ctypes.CDLL(lib_path)
|
|
183
|
+
except OSError:
|
|
184
|
+
try:
|
|
185
|
+
tmp_dir = Path(tempfile.gettempdir()) / "swpreq_lib"
|
|
186
|
+
tmp_dir.mkdir(parents=True, exist_ok=True)
|
|
187
|
+
tmp_path = tmp_dir / f"{os.getpid()}_{Path(lib_path).name}"
|
|
188
|
+
shutil.copy2(lib_path, tmp_path)
|
|
189
|
+
self.lib = ctypes.CDLL(str(tmp_path))
|
|
190
|
+
except OSError as e2:
|
|
191
|
+
raise FileLockedError(f"Failed to load library: {e2}")
|
|
192
|
+
|
|
193
|
+
self._setup_signatures()
|
|
194
|
+
|
|
195
|
+
def _setup_signatures(self) -> None:
|
|
196
|
+
lib = self.lib
|
|
197
|
+
|
|
198
|
+
# Version + memory
|
|
199
|
+
lib.swpreq_version.restype = ctypes.c_char_p
|
|
200
|
+
lib.swpreq_version.argtypes = []
|
|
201
|
+
|
|
202
|
+
lib.swpreq_string_free.restype = None
|
|
203
|
+
lib.swpreq_string_free.argtypes = [ctypes.c_char_p]
|
|
204
|
+
|
|
205
|
+
lib.swpreq_response_free.restype = None
|
|
206
|
+
lib.swpreq_response_free.argtypes = [ctypes.POINTER(SwpreqResponse)]
|
|
207
|
+
|
|
208
|
+
# Client
|
|
209
|
+
lib.swpreq_client_new.restype = ctypes.c_void_p
|
|
210
|
+
lib.swpreq_client_new.argtypes = [ctypes.c_char_p]
|
|
211
|
+
|
|
212
|
+
lib.swpreq_client_free.restype = None
|
|
213
|
+
lib.swpreq_client_free.argtypes = [ctypes.c_void_p]
|
|
214
|
+
|
|
215
|
+
# Headers + cookies
|
|
216
|
+
lib.swpreq_set_default_header.restype = ctypes.c_int
|
|
217
|
+
lib.swpreq_set_default_header.argtypes = [
|
|
218
|
+
ctypes.c_void_p,
|
|
219
|
+
ctypes.c_char_p,
|
|
220
|
+
ctypes.c_char_p,
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
lib.swpreq_remove_default_header.restype = ctypes.c_int
|
|
224
|
+
lib.swpreq_remove_default_header.argtypes = [
|
|
225
|
+
ctypes.c_void_p,
|
|
226
|
+
ctypes.c_char_p,
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
lib.swpreq_clear_default_headers.restype = ctypes.c_int
|
|
230
|
+
lib.swpreq_clear_default_headers.argtypes = [ctypes.c_void_p]
|
|
231
|
+
|
|
232
|
+
lib.swpreq_set_cookie.restype = ctypes.c_int
|
|
233
|
+
lib.swpreq_set_cookie.argtypes = [
|
|
234
|
+
ctypes.c_void_p,
|
|
235
|
+
ctypes.c_char_p,
|
|
236
|
+
ctypes.c_char_p,
|
|
237
|
+
ctypes.c_char_p,
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
lib.swpreq_clear_cookies.restype = ctypes.c_int
|
|
241
|
+
lib.swpreq_clear_cookies.argtypes = [ctypes.c_void_p]
|
|
242
|
+
|
|
243
|
+
# Request
|
|
244
|
+
lib.swpreq_request_sync.restype = ctypes.POINTER(SwpreqResponse)
|
|
245
|
+
lib.swpreq_request_sync.argtypes = [
|
|
246
|
+
ctypes.c_void_p,
|
|
247
|
+
ctypes.c_char_p,
|
|
248
|
+
ctypes.c_char_p,
|
|
249
|
+
ctypes.c_char_p,
|
|
250
|
+
ctypes.POINTER(ctypes.c_uint8),
|
|
251
|
+
ctypes.c_size_t,
|
|
252
|
+
ctypes.c_uint64,
|
|
253
|
+
ctypes.c_char_p,
|
|
254
|
+
ctypes.c_int64,
|
|
255
|
+
ctypes.c_int,
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
# Retry (optional)
|
|
259
|
+
if hasattr(lib, "swpreq_client_set_retry"):
|
|
260
|
+
lib.swpreq_client_set_retry.restype = ctypes.c_int
|
|
261
|
+
lib.swpreq_client_set_retry.argtypes = [
|
|
262
|
+
ctypes.c_void_p,
|
|
263
|
+
ctypes.c_uint32,
|
|
264
|
+
ctypes.c_uint64,
|
|
265
|
+
ctypes.c_int,
|
|
266
|
+
ctypes.c_int,
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
# WebSocket (optional)
|
|
270
|
+
if hasattr(lib, "swpreq_ws_connect"):
|
|
271
|
+
lib.swpreq_ws_connect.restype = ctypes.c_int
|
|
272
|
+
lib.swpreq_ws_connect.argtypes = [
|
|
273
|
+
ctypes.c_char_p,
|
|
274
|
+
ctypes.c_char_p,
|
|
275
|
+
ctypes.POINTER(ctypes.c_int),
|
|
276
|
+
ctypes.POINTER(ctypes.c_char_p),
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
lib.swpreq_ws_set_callbacks.restype = ctypes.c_int
|
|
280
|
+
lib.swpreq_ws_set_callbacks.argtypes = [
|
|
281
|
+
ctypes.c_int,
|
|
282
|
+
ctypes.c_void_p, ctypes.c_void_p,
|
|
283
|
+
ctypes.c_void_p, ctypes.c_void_p,
|
|
284
|
+
ctypes.c_void_p, ctypes.c_void_p,
|
|
285
|
+
ctypes.c_void_p, ctypes.c_void_p,
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
lib.swpreq_ws_send_text.restype = ctypes.c_int
|
|
289
|
+
lib.swpreq_ws_send_text.argtypes = [ctypes.c_int, ctypes.c_char_p]
|
|
290
|
+
|
|
291
|
+
lib.swpreq_ws_send_binary.restype = ctypes.c_int
|
|
292
|
+
lib.swpreq_ws_send_binary.argtypes = [
|
|
293
|
+
ctypes.c_int,
|
|
294
|
+
ctypes.POINTER(ctypes.c_uint8),
|
|
295
|
+
ctypes.c_size_t,
|
|
296
|
+
]
|
|
297
|
+
|
|
298
|
+
lib.swpreq_ws_send_ping.restype = ctypes.c_int
|
|
299
|
+
lib.swpreq_ws_send_ping.argtypes = [ctypes.c_int]
|
|
300
|
+
|
|
301
|
+
lib.swpreq_ws_close.restype = ctypes.c_int
|
|
302
|
+
lib.swpreq_ws_close.argtypes = [ctypes.c_int]
|
|
303
|
+
|
|
304
|
+
lib.swpreq_ws_free.restype = None
|
|
305
|
+
lib.swpreq_ws_free.argtypes = [ctypes.c_int]
|
|
306
|
+
|
|
307
|
+
def version(self) -> str:
|
|
308
|
+
v = self.lib.swpreq_version()
|
|
309
|
+
if not v:
|
|
310
|
+
return ""
|
|
311
|
+
return v.decode("utf-8")
|
|
312
|
+
|
|
313
|
+
def platform_info(self) -> dict:
|
|
314
|
+
os_name, arch = detect_platform()
|
|
315
|
+
return {
|
|
316
|
+
"os": os_name,
|
|
317
|
+
"arch": arch,
|
|
318
|
+
"supported": (os_name, arch) in SUPPORTED_PLATFORMS,
|
|
319
|
+
"library_name": SUPPORTED_PLATFORMS.get((os_name, arch)),
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
_core_instance: Optional[CoreLib] = None
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def get_lib() -> CoreLib:
|
|
327
|
+
global _core_instance
|
|
328
|
+
if _core_instance is None:
|
|
329
|
+
_core_instance = CoreLib()
|
|
330
|
+
return _core_instance
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def get_platform_info() -> dict:
|
|
334
|
+
return get_lib().platform_info()
|
swpreq/async_api.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from .client import Client
|
|
6
|
+
from .response import Response
|
|
7
|
+
from .streaming import ResponseStream
|
|
8
|
+
from .sse import SseStream
|
|
9
|
+
from .retry import RetryPolicy
|
|
10
|
+
from .hooks import Hooks
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AsyncClient:
|
|
14
|
+
def __init__(self, max_workers: int = 32, **client_kwargs):
|
|
15
|
+
self._sync = Client(**client_kwargs)
|
|
16
|
+
self._executor = ThreadPoolExecutor(
|
|
17
|
+
max_workers=max_workers, thread_name_prefix="swpreq"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
async def _run(self, fn, *args, **kwargs):
|
|
21
|
+
loop = asyncio.get_running_loop()
|
|
22
|
+
return await loop.run_in_executor(
|
|
23
|
+
self._executor, lambda: fn(*args, **kwargs)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
async def get(self, url: str, **kw) -> Response:
|
|
27
|
+
return await self._run(self._sync.get, url, **kw)
|
|
28
|
+
|
|
29
|
+
async def post(self, url: str, **kw) -> Response:
|
|
30
|
+
return await self._run(self._sync.post, url, **kw)
|
|
31
|
+
|
|
32
|
+
async def put(self, url: str, **kw) -> Response:
|
|
33
|
+
return await self._run(self._sync.put, url, **kw)
|
|
34
|
+
|
|
35
|
+
async def delete(self, url: str, **kw) -> Response:
|
|
36
|
+
return await self._run(self._sync.delete, url, **kw)
|
|
37
|
+
|
|
38
|
+
async def patch(self, url: str, **kw) -> Response:
|
|
39
|
+
return await self._run(self._sync.patch, url, **kw)
|
|
40
|
+
|
|
41
|
+
async def head(self, url: str, **kw) -> Response:
|
|
42
|
+
return await self._run(self._sync.head, url, **kw)
|
|
43
|
+
|
|
44
|
+
async def options(self, url: str, **kw) -> Response:
|
|
45
|
+
return await self._run(self._sync.options, url, **kw)
|
|
46
|
+
|
|
47
|
+
async def request(self, method: str, url: str, **kw) -> Response:
|
|
48
|
+
return await self._run(self._sync.request, method, url, **kw)
|
|
49
|
+
|
|
50
|
+
async def gather(self, *coros):
|
|
51
|
+
return await asyncio.gather(*coros)
|
|
52
|
+
|
|
53
|
+
async def map(self, urls, method: str = "GET", **kw):
|
|
54
|
+
tasks = [self.request(method, u, **kw) for u in urls]
|
|
55
|
+
return await asyncio.gather(*tasks)
|
|
56
|
+
|
|
57
|
+
async def stream(self, method: str, url: str, **kw) -> ResponseStream:
|
|
58
|
+
return self._sync.stream(method, url, **kw)
|
|
59
|
+
|
|
60
|
+
async def sse(self, url: str, headers=None, timeout=None) -> SseStream:
|
|
61
|
+
return self._sync.sse(url, headers=headers, timeout=timeout)
|
|
62
|
+
|
|
63
|
+
async def close(self):
|
|
64
|
+
self._executor.shutdown(wait=True)
|
|
65
|
+
self._sync.close()
|
|
66
|
+
|
|
67
|
+
async def __aenter__(self):
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
async def __aexit__(self, *args):
|
|
71
|
+
await self.close()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
AsyncSession = AsyncClient
|