quickspirit 2.1.0__py3-none-any.whl → 2.2.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.
- quickspirit/__init__.py +12 -12
- quickspirit/http_async_client.py +239 -206
- quickspirit/http_async_downloader.py +58 -33
- quickspirit/http_errors.py +10 -10
- quickspirit/models.py +10 -10
- {quickspirit-2.1.0.dist-info → quickspirit-2.2.0.dist-info}/METADATA +19 -13
- quickspirit-2.2.0.dist-info/RECORD +9 -0
- {quickspirit-2.1.0.dist-info → quickspirit-2.2.0.dist-info}/WHEEL +1 -1
- {quickspirit-2.1.0.dist-info → quickspirit-2.2.0.dist-info/licenses}/LICENSE +674 -674
- quickspirit-2.1.0.dist-info/RECORD +0 -9
quickspirit/__init__.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
from .http_async_downloader import HttpAsyncDownloader
|
|
2
|
-
from .http_errors import RequestError
|
|
3
|
-
from .http_async_client import HttpAsyncClient
|
|
4
|
-
from .models import Result
|
|
5
|
-
|
|
6
|
-
__all__ = [
|
|
7
|
-
"HttpAsyncDownloader",
|
|
8
|
-
"RequestError",
|
|
9
|
-
"HttpAsyncClient",
|
|
10
|
-
"Result",
|
|
11
|
-
"HttpAsyncClient",
|
|
12
|
-
]
|
|
1
|
+
from .http_async_downloader import HttpAsyncDownloader
|
|
2
|
+
from .http_errors import RequestError
|
|
3
|
+
from .http_async_client import HttpAsyncClient
|
|
4
|
+
from .models import Result
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"HttpAsyncDownloader",
|
|
8
|
+
"RequestError",
|
|
9
|
+
"HttpAsyncClient",
|
|
10
|
+
"Result",
|
|
11
|
+
"HttpAsyncClient",
|
|
12
|
+
]
|
quickspirit/http_async_client.py
CHANGED
|
@@ -1,206 +1,239 @@
|
|
|
1
|
-
from typing import Any, Callable, Dict, Optional
|
|
2
|
-
|
|
3
|
-
from httpx import AsyncClient, HTTPStatusError, Response
|
|
4
|
-
|
|
5
|
-
from .http_errors import RequestError
|
|
6
|
-
from .models import Result
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class HttpAsyncClient:
|
|
10
|
-
"""## Asynchronous HTTP client for making requests.
|
|
11
|
-
|
|
12
|
-
###
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
headers
|
|
83
|
-
url_params
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
) -> Result:
|
|
191
|
-
"""Make an HTTP
|
|
192
|
-
|
|
193
|
-
Args:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
1
|
+
from typing import Any, Callable, Dict, Optional
|
|
2
|
+
|
|
3
|
+
from httpx import AsyncClient, HTTPStatusError, Response, Timeout
|
|
4
|
+
|
|
5
|
+
from .http_errors import RequestError
|
|
6
|
+
from .models import Result
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HttpAsyncClient:
|
|
10
|
+
"""## Asynchronous HTTP client for making requests.
|
|
11
|
+
|
|
12
|
+
### Methods:
|
|
13
|
+
- send_request: inner function, modular call of the following requests:
|
|
14
|
+
- get
|
|
15
|
+
- post
|
|
16
|
+
- put
|
|
17
|
+
- patch
|
|
18
|
+
- delete
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, timeout: Timeout = Timeout(5)) -> None:
|
|
22
|
+
"""### The default client constructor.
|
|
23
|
+
|
|
24
|
+
### Args:
|
|
25
|
+
- timeout: Timeout - how much the client waits before cancelling the request.
|
|
26
|
+
"""
|
|
27
|
+
self.timeout: Timeout = timeout
|
|
28
|
+
|
|
29
|
+
async def get(
|
|
30
|
+
self,
|
|
31
|
+
url: str,
|
|
32
|
+
headers: Optional[Dict[str, str]] = None,
|
|
33
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
34
|
+
timeout: Optional[Timeout] = None,
|
|
35
|
+
) -> Result:
|
|
36
|
+
"""Make an HTTP GET request.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
url: The URL to send the request to.
|
|
40
|
+
headers: Optional headers to include in the request.
|
|
41
|
+
url_params: Optional URL parameters to include in the request.
|
|
42
|
+
timeout: Optional timeout, defaults to the client-level timeout.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The JSON response body as a dictionary or list, or a RequestError if there was an error.
|
|
46
|
+
"""
|
|
47
|
+
return await self.__send_request(
|
|
48
|
+
"get",
|
|
49
|
+
url,
|
|
50
|
+
headers=headers,
|
|
51
|
+
url_params=url_params,
|
|
52
|
+
timeout=timeout,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
async def post(
|
|
56
|
+
self,
|
|
57
|
+
url: str,
|
|
58
|
+
data: Optional[Dict[str, Any]] = None,
|
|
59
|
+
json: Optional[Dict[str, Any]] = None,
|
|
60
|
+
headers: Optional[Dict[str, str]] = None,
|
|
61
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
62
|
+
files: Optional[Dict[str, Any]] = None,
|
|
63
|
+
timeout: Optional[Timeout] = None,
|
|
64
|
+
) -> Result:
|
|
65
|
+
"""Make an HTTP POST request.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
url: The URL to send the request to.
|
|
69
|
+
body: The request body as a dictionary.
|
|
70
|
+
headers: Optional headers to include in the request.
|
|
71
|
+
url_params: Optional URL parameters to include in the request.
|
|
72
|
+
timeout: Optional timeout, defaults to the client-level timeout.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
The JSON response body as a dictionary or list, or a RequestError if there was an error.
|
|
76
|
+
"""
|
|
77
|
+
return await self.__send_request(
|
|
78
|
+
"post",
|
|
79
|
+
url,
|
|
80
|
+
data=data,
|
|
81
|
+
json=json,
|
|
82
|
+
headers=headers,
|
|
83
|
+
url_params=url_params,
|
|
84
|
+
files=files,
|
|
85
|
+
timeout=timeout,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
async def put(
|
|
89
|
+
self,
|
|
90
|
+
url: str,
|
|
91
|
+
data: Optional[Dict[str, Any]] = None,
|
|
92
|
+
json: Optional[Dict[str, Any]] = None,
|
|
93
|
+
headers: Optional[Dict[str, str]] = None,
|
|
94
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
95
|
+
files: Optional[Dict[str, Any]] = None,
|
|
96
|
+
timeout: Optional[Timeout] = None,
|
|
97
|
+
) -> Result:
|
|
98
|
+
"""Make an HTTP PUT request.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
url: The URL to send the request to.
|
|
102
|
+
body: The request body as a dictionary.
|
|
103
|
+
headers: Optional headers to include in the request.
|
|
104
|
+
url_params: Optional URL parameters to include in the request.
|
|
105
|
+
timeout: Optional timeout, defaults to the client-level timeout.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
The JSON response body as a dictionary or list, or a RequestError if there was an error.
|
|
109
|
+
"""
|
|
110
|
+
return await self.__send_request(
|
|
111
|
+
"put",
|
|
112
|
+
url,
|
|
113
|
+
data=data,
|
|
114
|
+
json=json,
|
|
115
|
+
headers=headers,
|
|
116
|
+
url_params=url_params,
|
|
117
|
+
files=files,
|
|
118
|
+
timeout=timeout,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
async def patch(
|
|
122
|
+
self,
|
|
123
|
+
url: str,
|
|
124
|
+
data: Optional[Dict[str, Any]] = None,
|
|
125
|
+
json: Optional[Dict[str, Any]] = None,
|
|
126
|
+
headers: Optional[Dict[str, str]] = None,
|
|
127
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
128
|
+
files: Optional[Dict[str, Any]] = None,
|
|
129
|
+
timeout: Optional[Timeout] = None,
|
|
130
|
+
) -> Result:
|
|
131
|
+
"""Make an HTTP PATCH request.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
url: The URL to send the request to.
|
|
135
|
+
body: The request body as a dictionary.
|
|
136
|
+
headers: Optional headers to include in the request.
|
|
137
|
+
url_params: Optional URL parameters to include in the request.
|
|
138
|
+
timeout: Optional[Timeout] = None,
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
The JSON response body as a dictionary or list, or a RequestError if there was an error.
|
|
142
|
+
"""
|
|
143
|
+
return await self.__send_request(
|
|
144
|
+
"patch",
|
|
145
|
+
url,
|
|
146
|
+
data=data,
|
|
147
|
+
json=json,
|
|
148
|
+
headers=headers,
|
|
149
|
+
url_params=url_params,
|
|
150
|
+
files=files,
|
|
151
|
+
timeout=timeout,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
async def delete(
|
|
155
|
+
self,
|
|
156
|
+
url: str,
|
|
157
|
+
headers: Optional[Dict[str, str]] = None,
|
|
158
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
159
|
+
timeout: Optional[Timeout] = None,
|
|
160
|
+
) -> Result:
|
|
161
|
+
"""Make an HTTP DELETE request.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
url: The URL to send the request to.
|
|
165
|
+
headers: Optional headers to include in the request.
|
|
166
|
+
url_params: Optional URL parameters to include in the request.
|
|
167
|
+
timeout: Optional timeout, defaults to the client-level timeout.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
The JSON response body as a dictionary or list, or a RequestError if there was an error.
|
|
171
|
+
"""
|
|
172
|
+
return await self.__send_request(
|
|
173
|
+
"delete",
|
|
174
|
+
url,
|
|
175
|
+
headers=headers,
|
|
176
|
+
url_params=url_params,
|
|
177
|
+
timeout=timeout,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
async def __send_request(
|
|
181
|
+
self,
|
|
182
|
+
method: str,
|
|
183
|
+
url: str,
|
|
184
|
+
data: Optional[Dict[str, Any]] = None,
|
|
185
|
+
json: Optional[Dict[str, Any]] = None,
|
|
186
|
+
headers: Optional[Dict[str, str]] = None,
|
|
187
|
+
url_params: Optional[Dict[str, Any]] = None,
|
|
188
|
+
files: Optional[Dict[str, Any]] = None,
|
|
189
|
+
timeout: Optional[Timeout] = None,
|
|
190
|
+
) -> Result:
|
|
191
|
+
"""Make an HTTP request using the specified method.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
method: The HTTP method to use (e.g., "get", "post").
|
|
195
|
+
url: The URL to send the request to.
|
|
196
|
+
body: The request body as a dictionary.
|
|
197
|
+
headers: Optional headers to include in the request.
|
|
198
|
+
url_params: Optional URL parameters to include in the request.
|
|
199
|
+
files: Optional file uris to upload.
|
|
200
|
+
timeout: Optional timeout, defaults to the client-level timeout.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
A Result instance representing either the RAW response body
|
|
204
|
+
or a RequestError if there was an error.
|
|
205
|
+
|
|
206
|
+
Raises:
|
|
207
|
+
RequestError: If there was an error in the request.
|
|
208
|
+
"""
|
|
209
|
+
try:
|
|
210
|
+
async with AsyncClient(timeout=self.timeout) as client:
|
|
211
|
+
request_method: Callable = getattr(client, method)
|
|
212
|
+
|
|
213
|
+
if method in {"get", "delete"}:
|
|
214
|
+
response: Response = await request_method(
|
|
215
|
+
url,
|
|
216
|
+
headers=headers,
|
|
217
|
+
params=url_params,
|
|
218
|
+
timeout=timeout or self.timeout,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
else:
|
|
222
|
+
response = await request_method(
|
|
223
|
+
url,
|
|
224
|
+
data=data,
|
|
225
|
+
json=json,
|
|
226
|
+
headers=headers,
|
|
227
|
+
params=url_params,
|
|
228
|
+
files=files,
|
|
229
|
+
timeout=timeout or self.timeout,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
response.raise_for_status()
|
|
233
|
+
|
|
234
|
+
return Result(data=response.read(), error=None)
|
|
235
|
+
|
|
236
|
+
except HTTPStatusError as exec:
|
|
237
|
+
error_message = f"Endpoint returned: {exec.response.text}\n"
|
|
238
|
+
|
|
239
|
+
return Result(error=RequestError(error_message), data=None)
|
|
@@ -1,33 +1,58 @@
|
|
|
1
|
-
from typing import Any, Dict
|
|
2
|
-
|
|
3
|
-
import aiofiles
|
|
4
|
-
from httpx import AsyncClient
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class HttpAsyncDownloader:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
import aiofiles
|
|
4
|
+
from httpx import AsyncClient, Timeout
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HttpAsyncDownloader:
|
|
8
|
+
"""## Asynchronous HTTP downloader.
|
|
9
|
+
|
|
10
|
+
### Methods:
|
|
11
|
+
- send_request: inner function, modular call of the following requests:
|
|
12
|
+
- get
|
|
13
|
+
- post
|
|
14
|
+
- put
|
|
15
|
+
- patch
|
|
16
|
+
- delete
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, timeout: Timeout = Timeout(5)) -> None:
|
|
20
|
+
"""### The default downloader constructor.
|
|
21
|
+
|
|
22
|
+
### Args:
|
|
23
|
+
- timeout: Timeout - how much the client waits before cancelling the request.
|
|
24
|
+
"""
|
|
25
|
+
self.timeout: Timeout = timeout
|
|
26
|
+
|
|
27
|
+
async def __send_request(
|
|
28
|
+
self,
|
|
29
|
+
method: str,
|
|
30
|
+
url: str,
|
|
31
|
+
file_name: str,
|
|
32
|
+
data: Dict[str, Any] | None = None,
|
|
33
|
+
json: Dict[str, Any] | None = None,
|
|
34
|
+
headers: Dict[str, str] | None = None,
|
|
35
|
+
url_params: Dict[str, Any] | None = None,
|
|
36
|
+
timeout: Timeout | None = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
async with AsyncClient() as client:
|
|
39
|
+
async with client.stream(
|
|
40
|
+
method=method,
|
|
41
|
+
url=url,
|
|
42
|
+
data=data,
|
|
43
|
+
json=json,
|
|
44
|
+
headers=headers,
|
|
45
|
+
params=url_params,
|
|
46
|
+
timeout=timeout,
|
|
47
|
+
) as response:
|
|
48
|
+
async with aiofiles.open(file_name, "wb") as f:
|
|
49
|
+
async for chunk in response.aiter_bytes():
|
|
50
|
+
if chunk:
|
|
51
|
+
await f.write(chunk)
|
|
52
|
+
|
|
53
|
+
async def get_file_from_url(
|
|
54
|
+
self, url: str, file_path: str, timeout: Timeout | None = Timeout(50)
|
|
55
|
+
) -> None:
|
|
56
|
+
await self.__send_request(
|
|
57
|
+
"GET", url, file_path, timeout=timeout or self.timeout
|
|
58
|
+
)
|
quickspirit/http_errors.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
class RequestError(Exception):
|
|
2
|
-
"""Exception raised for request errors.
|
|
3
|
-
|
|
4
|
-
Attributes:
|
|
5
|
-
message -- Explanation of the error.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
def __init__(self, message: str) -> None:
|
|
9
|
-
self.message = message
|
|
10
|
-
super().__init__(self.message)
|
|
1
|
+
class RequestError(Exception):
|
|
2
|
+
"""Exception raised for request errors.
|
|
3
|
+
|
|
4
|
+
Attributes:
|
|
5
|
+
message -- Explanation of the error.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
def __init__(self, message: str) -> None:
|
|
9
|
+
self.message = message
|
|
10
|
+
super().__init__(self.message)
|
quickspirit/models.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from .http_errors import RequestError
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
8
|
-
class Result:
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from .http_errors import RequestError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Result:
|
|
9
|
+
error: Optional[RequestError]
|
|
10
|
+
data: Optional[bytes]
|