httpr 0.1.17__cp39-abi3-win_amd64.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.
- httpr/__init__.py +870 -0
- httpr/httpr.pyd +0 -0
- httpr/httpr.pyi +101 -0
- httpr/py.typed +0 -0
- httpr-0.1.17.dist-info/METADATA +49 -0
- httpr-0.1.17.dist-info/RECORD +8 -0
- httpr-0.1.17.dist-info/WHEEL +4 -0
- httpr-0.1.17.dist-info/licenses/LICENSE +21 -0
httpr/__init__.py
ADDED
|
@@ -0,0 +1,870 @@
|
|
|
1
|
+
"""
|
|
2
|
+
httpr - Blazing fast HTTP client for Python, built in Rust.
|
|
3
|
+
|
|
4
|
+
httpr is a high-performance HTTP client that can be used as a drop-in replacement
|
|
5
|
+
for `httpx` and `requests` in most cases.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
Simple GET request:
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
import httpr
|
|
12
|
+
|
|
13
|
+
response = httpr.get("https://httpbin.org/get")
|
|
14
|
+
print(response.json())
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Using a client for connection pooling:
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import httpr
|
|
21
|
+
|
|
22
|
+
with httpr.Client() as client:
|
|
23
|
+
response = client.get("https://httpbin.org/get")
|
|
24
|
+
print(response.status_code)
|
|
25
|
+
```
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import asyncio
|
|
31
|
+
import sys
|
|
32
|
+
from functools import partial
|
|
33
|
+
from typing import TYPE_CHECKING, Any, TypedDict
|
|
34
|
+
|
|
35
|
+
if sys.version_info <= (3, 11):
|
|
36
|
+
from typing_extensions import Unpack
|
|
37
|
+
else:
|
|
38
|
+
from typing import Unpack
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
from .httpr import RClient
|
|
42
|
+
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
from .httpr import ClientRequestParams, HttpMethod, RequestParams, Response
|
|
45
|
+
else:
|
|
46
|
+
|
|
47
|
+
class _Unpack:
|
|
48
|
+
@staticmethod
|
|
49
|
+
def __getitem__(*args, **kwargs):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
Unpack = _Unpack()
|
|
53
|
+
RequestParams = ClientRequestParams = TypedDict
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Client(RClient):
|
|
57
|
+
"""
|
|
58
|
+
A synchronous HTTP client with connection pooling.
|
|
59
|
+
|
|
60
|
+
The Client class provides a high-level interface for making HTTP requests.
|
|
61
|
+
It supports connection pooling, automatic cookie handling, and various
|
|
62
|
+
authentication methods.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
Basic usage:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import httpr
|
|
69
|
+
|
|
70
|
+
# Using context manager (recommended)
|
|
71
|
+
with httpr.Client() as client:
|
|
72
|
+
response = client.get("https://httpbin.org/get")
|
|
73
|
+
print(response.json())
|
|
74
|
+
|
|
75
|
+
# Or manually
|
|
76
|
+
client = httpr.Client()
|
|
77
|
+
response = client.get("https://httpbin.org/get")
|
|
78
|
+
client.close()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
With configuration:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import httpr
|
|
85
|
+
|
|
86
|
+
client = httpr.Client(
|
|
87
|
+
auth_bearer="your-api-token",
|
|
88
|
+
headers={"User-Agent": "my-app/1.0"},
|
|
89
|
+
timeout=30,
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Attributes:
|
|
94
|
+
headers: Default headers sent with all requests. Excludes Cookie header.
|
|
95
|
+
cookies: Default cookies sent with all requests.
|
|
96
|
+
auth: Basic auth credentials as (username, password) tuple.
|
|
97
|
+
params: Default query parameters added to all requests.
|
|
98
|
+
timeout: Default timeout in seconds.
|
|
99
|
+
proxy: Proxy URL for requests.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
auth: tuple[str, str | None] | None = None,
|
|
105
|
+
auth_bearer: str | None = None,
|
|
106
|
+
params: dict[str, str] | None = None,
|
|
107
|
+
headers: dict[str, str] | None = None,
|
|
108
|
+
cookies: dict[str, str] | None = None,
|
|
109
|
+
cookie_store: bool | None = True,
|
|
110
|
+
referer: bool | None = True,
|
|
111
|
+
proxy: str | None = None,
|
|
112
|
+
timeout: float | None = 30,
|
|
113
|
+
follow_redirects: bool | None = True,
|
|
114
|
+
max_redirects: int | None = 20,
|
|
115
|
+
verify: bool | None = True,
|
|
116
|
+
ca_cert_file: str | None = None,
|
|
117
|
+
client_pem: str | None = None,
|
|
118
|
+
https_only: bool | None = False,
|
|
119
|
+
http2_only: bool | None = False,
|
|
120
|
+
):
|
|
121
|
+
"""
|
|
122
|
+
Initialize an HTTP client.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
auth: Basic auth credentials as (username, password). Password can be None.
|
|
126
|
+
auth_bearer: Bearer token for Authorization header.
|
|
127
|
+
params: Default query parameters to include in all requests.
|
|
128
|
+
headers: Default headers to send with all requests.
|
|
129
|
+
cookies: Default cookies to send with all requests.
|
|
130
|
+
cookie_store: Enable persistent cookie store. Cookies from responses will be
|
|
131
|
+
preserved and included in subsequent requests. Default is True.
|
|
132
|
+
referer: Automatically set Referer header. Default is True.
|
|
133
|
+
proxy: Proxy URL (e.g., "http://proxy:8080" or "socks5://127.0.0.1:1080").
|
|
134
|
+
Falls back to HTTPR_PROXY environment variable.
|
|
135
|
+
timeout: Request timeout in seconds. Default is 30.
|
|
136
|
+
follow_redirects: Follow HTTP redirects. Default is True.
|
|
137
|
+
max_redirects: Maximum redirects to follow. Default is 20.
|
|
138
|
+
verify: Verify SSL certificates. Default is True.
|
|
139
|
+
ca_cert_file: Path to CA certificate bundle (PEM format).
|
|
140
|
+
client_pem: Path to client certificate for mTLS (PEM format).
|
|
141
|
+
https_only: Only allow HTTPS requests. Default is False.
|
|
142
|
+
http2_only: Use HTTP/2 only (False uses HTTP/1.1). Default is False.
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
```python
|
|
146
|
+
import httpr
|
|
147
|
+
|
|
148
|
+
# Simple client
|
|
149
|
+
client = httpr.Client()
|
|
150
|
+
|
|
151
|
+
# Client with authentication
|
|
152
|
+
client = httpr.Client(
|
|
153
|
+
auth=("username", "password"),
|
|
154
|
+
timeout=60,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Client with bearer token
|
|
158
|
+
client = httpr.Client(
|
|
159
|
+
auth_bearer="your-api-token",
|
|
160
|
+
headers={"Accept": "application/json"},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Client with proxy
|
|
164
|
+
client = httpr.Client(proxy="http://proxy.example.com:8080")
|
|
165
|
+
|
|
166
|
+
# Client with mTLS
|
|
167
|
+
client = httpr.Client(
|
|
168
|
+
client_pem="/path/to/client.pem",
|
|
169
|
+
ca_cert_file="/path/to/ca.pem",
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
"""
|
|
173
|
+
super().__init__()
|
|
174
|
+
|
|
175
|
+
def __enter__(self) -> Client:
|
|
176
|
+
"""Enter context manager."""
|
|
177
|
+
return self
|
|
178
|
+
|
|
179
|
+
def __exit__(self, *args):
|
|
180
|
+
"""Exit context manager and close client."""
|
|
181
|
+
del self
|
|
182
|
+
|
|
183
|
+
def close(self) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Close the client and release resources.
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
```python
|
|
189
|
+
client = httpr.Client()
|
|
190
|
+
try:
|
|
191
|
+
response = client.get("https://example.com")
|
|
192
|
+
finally:
|
|
193
|
+
client.close()
|
|
194
|
+
```
|
|
195
|
+
"""
|
|
196
|
+
del self
|
|
197
|
+
|
|
198
|
+
def request(
|
|
199
|
+
self,
|
|
200
|
+
method: HttpMethod,
|
|
201
|
+
url: str,
|
|
202
|
+
**kwargs: Unpack[RequestParams],
|
|
203
|
+
) -> Response:
|
|
204
|
+
"""
|
|
205
|
+
Make an HTTP request.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
method: HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS).
|
|
209
|
+
url: Request URL.
|
|
210
|
+
**kwargs: Request parameters (see below).
|
|
211
|
+
|
|
212
|
+
Keyword Args:
|
|
213
|
+
params (dict[str, str] | None): Query parameters to append to URL.
|
|
214
|
+
headers (dict[str, str] | None): Request headers (merged with client defaults).
|
|
215
|
+
cookies (dict[str, str] | None): Request cookies (merged with client defaults).
|
|
216
|
+
auth (tuple[str, str | None] | None): Basic auth credentials (overrides client default).
|
|
217
|
+
auth_bearer (str | None): Bearer token (overrides client default).
|
|
218
|
+
timeout (float | None): Request timeout in seconds (overrides client default).
|
|
219
|
+
content (bytes | None): Raw bytes for request body.
|
|
220
|
+
data (dict[str, Any] | None): Form data for request body (application/x-www-form-urlencoded).
|
|
221
|
+
json (Any | None): JSON data for request body (application/json).
|
|
222
|
+
files (dict[str, str] | None): Files for multipart upload (dict mapping field names to file paths).
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
Response object with status, headers, and body.
|
|
226
|
+
|
|
227
|
+
Raises:
|
|
228
|
+
ValueError: If method is not a valid HTTP method.
|
|
229
|
+
Exception: If request fails (timeout, connection error, etc.).
|
|
230
|
+
|
|
231
|
+
Example:
|
|
232
|
+
```python
|
|
233
|
+
response = client.request("GET", "https://httpbin.org/get")
|
|
234
|
+
response = client.request("POST", "https://httpbin.org/post", json={"key": "value"})
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Note:
|
|
238
|
+
Only one of `content`, `data`, `json`, or `files` can be specified per request.
|
|
239
|
+
"""
|
|
240
|
+
if method not in ["GET", "HEAD", "OPTIONS", "DELETE", "POST", "PUT", "PATCH"]:
|
|
241
|
+
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
242
|
+
if "params" in kwargs and kwargs["params"] is not None:
|
|
243
|
+
kwargs["params"] = {k: str(v) for k, v in kwargs["params"].items()}
|
|
244
|
+
|
|
245
|
+
return super().request(method=method, url=url, **kwargs)
|
|
246
|
+
|
|
247
|
+
def get(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
248
|
+
"""
|
|
249
|
+
Make a GET request.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
url: Request URL.
|
|
253
|
+
**kwargs: Request parameters (params, headers, cookies, auth, auth_bearer, timeout).
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
Response object.
|
|
257
|
+
|
|
258
|
+
Example:
|
|
259
|
+
```python
|
|
260
|
+
response = client.get(
|
|
261
|
+
"https://httpbin.org/get",
|
|
262
|
+
params={"key": "value"},
|
|
263
|
+
headers={"Accept": "application/json"},
|
|
264
|
+
)
|
|
265
|
+
print(response.json())
|
|
266
|
+
```
|
|
267
|
+
"""
|
|
268
|
+
return self.request(method="GET", url=url, **kwargs)
|
|
269
|
+
|
|
270
|
+
def head(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
271
|
+
"""
|
|
272
|
+
Make a HEAD request.
|
|
273
|
+
|
|
274
|
+
Returns only headers, no response body.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
url: Request URL.
|
|
278
|
+
**kwargs: Request parameters (params, headers, cookies, auth, auth_bearer, timeout).
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Response object (body will be empty).
|
|
282
|
+
|
|
283
|
+
Example:
|
|
284
|
+
```python
|
|
285
|
+
response = client.head("https://httpbin.org/get")
|
|
286
|
+
print(response.headers["content-length"])
|
|
287
|
+
```
|
|
288
|
+
"""
|
|
289
|
+
return self.request(method="HEAD", url=url, **kwargs)
|
|
290
|
+
|
|
291
|
+
def options(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
292
|
+
"""
|
|
293
|
+
Make an OPTIONS request.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
url: Request URL.
|
|
297
|
+
**kwargs: Request parameters (params, headers, cookies, auth, auth_bearer, timeout).
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Response object.
|
|
301
|
+
|
|
302
|
+
Example:
|
|
303
|
+
```python
|
|
304
|
+
response = client.options("https://httpbin.org/get")
|
|
305
|
+
print(response.headers.get("allow"))
|
|
306
|
+
```
|
|
307
|
+
"""
|
|
308
|
+
return self.request(method="OPTIONS", url=url, **kwargs)
|
|
309
|
+
|
|
310
|
+
def delete(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
311
|
+
"""
|
|
312
|
+
Make a DELETE request.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
url: Request URL.
|
|
316
|
+
**kwargs: Request parameters (params, headers, cookies, auth, auth_bearer, timeout).
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Response object.
|
|
320
|
+
|
|
321
|
+
Example:
|
|
322
|
+
```python
|
|
323
|
+
response = client.delete("https://httpbin.org/delete")
|
|
324
|
+
print(response.status_code)
|
|
325
|
+
```
|
|
326
|
+
"""
|
|
327
|
+
return self.request(method="DELETE", url=url, **kwargs)
|
|
328
|
+
|
|
329
|
+
def post(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
330
|
+
"""
|
|
331
|
+
Make a POST request.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
url: Request URL.
|
|
335
|
+
**kwargs: Request parameters including body options.
|
|
336
|
+
|
|
337
|
+
Keyword Args:
|
|
338
|
+
params (dict[str, str] | None): Query parameters.
|
|
339
|
+
headers (dict[str, str] | None): Request headers.
|
|
340
|
+
cookies (dict[str, str] | None): Request cookies.
|
|
341
|
+
auth (tuple[str, str | None] | None): Basic auth credentials.
|
|
342
|
+
auth_bearer (str | None): Bearer token.
|
|
343
|
+
timeout (float | None): Request timeout.
|
|
344
|
+
content (bytes | None): Raw bytes body.
|
|
345
|
+
data (dict[str, Any] | None): Form-encoded body.
|
|
346
|
+
json (Any | None): JSON body.
|
|
347
|
+
files (dict[str, str] | None): Multipart file uploads.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
Response object.
|
|
351
|
+
|
|
352
|
+
Example:
|
|
353
|
+
```python
|
|
354
|
+
# JSON body
|
|
355
|
+
response = client.post(
|
|
356
|
+
"https://httpbin.org/post",
|
|
357
|
+
json={"name": "httpr", "fast": True},
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
# Form data
|
|
361
|
+
response = client.post(
|
|
362
|
+
"https://httpbin.org/post",
|
|
363
|
+
data={"username": "user", "password": "pass"},
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# File upload
|
|
367
|
+
response = client.post(
|
|
368
|
+
"https://httpbin.org/post",
|
|
369
|
+
files={"document": "/path/to/file.pdf"},
|
|
370
|
+
)
|
|
371
|
+
```
|
|
372
|
+
"""
|
|
373
|
+
return self.request(method="POST", url=url, **kwargs)
|
|
374
|
+
|
|
375
|
+
def put(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
376
|
+
"""
|
|
377
|
+
Make a PUT request.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
url: Request URL.
|
|
381
|
+
**kwargs: Request parameters including body options.
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
Response object.
|
|
385
|
+
|
|
386
|
+
Example:
|
|
387
|
+
```python
|
|
388
|
+
response = client.put(
|
|
389
|
+
"https://httpbin.org/put",
|
|
390
|
+
json={"key": "updated_value"},
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
"""
|
|
394
|
+
return self.request(method="PUT", url=url, **kwargs)
|
|
395
|
+
|
|
396
|
+
def patch(self, url: str, **kwargs: Unpack[RequestParams]) -> Response:
|
|
397
|
+
"""
|
|
398
|
+
Make a PATCH request.
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
url: Request URL.
|
|
402
|
+
**kwargs: Request parameters including body options.
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
Response object.
|
|
406
|
+
|
|
407
|
+
Example:
|
|
408
|
+
```python
|
|
409
|
+
response = client.patch(
|
|
410
|
+
"https://httpbin.org/patch",
|
|
411
|
+
json={"field": "new_value"},
|
|
412
|
+
)
|
|
413
|
+
```
|
|
414
|
+
"""
|
|
415
|
+
return self.request(method="PATCH", url=url, **kwargs)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
class AsyncClient(Client):
|
|
419
|
+
"""
|
|
420
|
+
An asynchronous HTTP client for use with asyncio.
|
|
421
|
+
|
|
422
|
+
AsyncClient wraps the synchronous Client using asyncio.run_in_executor(),
|
|
423
|
+
providing an async interface while leveraging the Rust implementation's
|
|
424
|
+
performance.
|
|
425
|
+
|
|
426
|
+
Example:
|
|
427
|
+
Basic usage:
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
import asyncio
|
|
431
|
+
import httpr
|
|
432
|
+
|
|
433
|
+
async def main():
|
|
434
|
+
async with httpr.AsyncClient() as client:
|
|
435
|
+
response = await client.get("https://httpbin.org/get")
|
|
436
|
+
print(response.json())
|
|
437
|
+
|
|
438
|
+
asyncio.run(main())
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Concurrent requests:
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
import asyncio
|
|
445
|
+
import httpr
|
|
446
|
+
|
|
447
|
+
async def main():
|
|
448
|
+
async with httpr.AsyncClient() as client:
|
|
449
|
+
tasks = [
|
|
450
|
+
client.get("https://httpbin.org/get"),
|
|
451
|
+
client.get("https://httpbin.org/ip"),
|
|
452
|
+
]
|
|
453
|
+
responses = await asyncio.gather(*tasks)
|
|
454
|
+
for response in responses:
|
|
455
|
+
print(response.json())
|
|
456
|
+
|
|
457
|
+
asyncio.run(main())
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Note:
|
|
461
|
+
AsyncClient runs synchronous Rust code in a thread executor.
|
|
462
|
+
It provides concurrency benefits for I/O-bound tasks but is not
|
|
463
|
+
native async I/O.
|
|
464
|
+
"""
|
|
465
|
+
|
|
466
|
+
def __init__(self, *args, **kwargs):
|
|
467
|
+
"""
|
|
468
|
+
Initialize an async HTTP client.
|
|
469
|
+
|
|
470
|
+
Accepts the same parameters as Client.
|
|
471
|
+
"""
|
|
472
|
+
super().__init__(*args, **kwargs)
|
|
473
|
+
|
|
474
|
+
async def __aenter__(self) -> AsyncClient:
|
|
475
|
+
"""Enter async context manager."""
|
|
476
|
+
return self
|
|
477
|
+
|
|
478
|
+
async def __aexit__(self, *args):
|
|
479
|
+
"""Exit async context manager and close client."""
|
|
480
|
+
del self
|
|
481
|
+
|
|
482
|
+
async def aclose(self):
|
|
483
|
+
"""
|
|
484
|
+
Close the async client.
|
|
485
|
+
|
|
486
|
+
Example:
|
|
487
|
+
```python
|
|
488
|
+
client = httpr.AsyncClient()
|
|
489
|
+
try:
|
|
490
|
+
response = await client.get("https://example.com")
|
|
491
|
+
finally:
|
|
492
|
+
await client.aclose()
|
|
493
|
+
```
|
|
494
|
+
"""
|
|
495
|
+
del self
|
|
496
|
+
return
|
|
497
|
+
|
|
498
|
+
async def _run_sync_asyncio(self, fn, *args, **kwargs):
|
|
499
|
+
"""Run a synchronous function in an executor."""
|
|
500
|
+
loop = asyncio.get_running_loop()
|
|
501
|
+
return await loop.run_in_executor(None, partial(fn, *args, **kwargs))
|
|
502
|
+
|
|
503
|
+
async def request( # type: ignore[override]
|
|
504
|
+
self,
|
|
505
|
+
method: HttpMethod,
|
|
506
|
+
url: str,
|
|
507
|
+
**kwargs: Unpack[RequestParams],
|
|
508
|
+
) -> Response:
|
|
509
|
+
"""
|
|
510
|
+
Make an async HTTP request.
|
|
511
|
+
|
|
512
|
+
Args:
|
|
513
|
+
method: HTTP method.
|
|
514
|
+
url: Request URL.
|
|
515
|
+
**kwargs: Request parameters.
|
|
516
|
+
|
|
517
|
+
Returns:
|
|
518
|
+
Response object.
|
|
519
|
+
|
|
520
|
+
Example:
|
|
521
|
+
```python
|
|
522
|
+
response = await client.request("GET", "https://httpbin.org/get")
|
|
523
|
+
```
|
|
524
|
+
"""
|
|
525
|
+
if method not in ["GET", "HEAD", "OPTIONS", "DELETE", "POST", "PUT", "PATCH"]:
|
|
526
|
+
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
527
|
+
if "params" in kwargs and kwargs["params"] is not None:
|
|
528
|
+
kwargs["params"] = {k: str(v) for k, v in kwargs["params"].items()}
|
|
529
|
+
|
|
530
|
+
return await self._run_sync_asyncio(super().request, method=method, url=url, **kwargs)
|
|
531
|
+
|
|
532
|
+
async def get( # type: ignore[override]
|
|
533
|
+
self,
|
|
534
|
+
url: str,
|
|
535
|
+
**kwargs: Unpack[RequestParams],
|
|
536
|
+
) -> Response:
|
|
537
|
+
"""
|
|
538
|
+
Make an async GET request.
|
|
539
|
+
|
|
540
|
+
Args:
|
|
541
|
+
url: Request URL.
|
|
542
|
+
**kwargs: Request parameters.
|
|
543
|
+
|
|
544
|
+
Returns:
|
|
545
|
+
Response object.
|
|
546
|
+
|
|
547
|
+
Example:
|
|
548
|
+
```python
|
|
549
|
+
response = await client.get("https://httpbin.org/get")
|
|
550
|
+
```
|
|
551
|
+
"""
|
|
552
|
+
return await self.request(method="GET", url=url, **kwargs)
|
|
553
|
+
|
|
554
|
+
async def head( # type: ignore[override]
|
|
555
|
+
self,
|
|
556
|
+
url: str,
|
|
557
|
+
**kwargs: Unpack[RequestParams],
|
|
558
|
+
) -> Response:
|
|
559
|
+
"""
|
|
560
|
+
Make an async HEAD request.
|
|
561
|
+
|
|
562
|
+
Args:
|
|
563
|
+
url: Request URL.
|
|
564
|
+
**kwargs: Request parameters.
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
Response object.
|
|
568
|
+
"""
|
|
569
|
+
return await self.request(method="HEAD", url=url, **kwargs)
|
|
570
|
+
|
|
571
|
+
async def options( # type: ignore[override]
|
|
572
|
+
self,
|
|
573
|
+
url: str,
|
|
574
|
+
**kwargs: Unpack[RequestParams],
|
|
575
|
+
) -> Response:
|
|
576
|
+
"""
|
|
577
|
+
Make an async OPTIONS request.
|
|
578
|
+
|
|
579
|
+
Args:
|
|
580
|
+
url: Request URL.
|
|
581
|
+
**kwargs: Request parameters.
|
|
582
|
+
|
|
583
|
+
Returns:
|
|
584
|
+
Response object.
|
|
585
|
+
"""
|
|
586
|
+
return await self.request(method="OPTIONS", url=url, **kwargs)
|
|
587
|
+
|
|
588
|
+
async def delete( # type: ignore[override]
|
|
589
|
+
self,
|
|
590
|
+
url: str,
|
|
591
|
+
**kwargs: Unpack[RequestParams],
|
|
592
|
+
) -> Response:
|
|
593
|
+
"""
|
|
594
|
+
Make an async DELETE request.
|
|
595
|
+
|
|
596
|
+
Args:
|
|
597
|
+
url: Request URL.
|
|
598
|
+
**kwargs: Request parameters.
|
|
599
|
+
|
|
600
|
+
Returns:
|
|
601
|
+
Response object.
|
|
602
|
+
"""
|
|
603
|
+
return await self.request(method="DELETE", url=url, **kwargs)
|
|
604
|
+
|
|
605
|
+
async def post( # type: ignore[override]
|
|
606
|
+
self,
|
|
607
|
+
url: str,
|
|
608
|
+
**kwargs: Unpack[RequestParams],
|
|
609
|
+
) -> Response:
|
|
610
|
+
"""
|
|
611
|
+
Make an async POST request.
|
|
612
|
+
|
|
613
|
+
Args:
|
|
614
|
+
url: Request URL.
|
|
615
|
+
**kwargs: Request parameters including body options.
|
|
616
|
+
|
|
617
|
+
Returns:
|
|
618
|
+
Response object.
|
|
619
|
+
|
|
620
|
+
Example:
|
|
621
|
+
```python
|
|
622
|
+
response = await client.post(
|
|
623
|
+
"https://httpbin.org/post",
|
|
624
|
+
json={"key": "value"},
|
|
625
|
+
)
|
|
626
|
+
```
|
|
627
|
+
"""
|
|
628
|
+
return await self.request(method="POST", url=url, **kwargs)
|
|
629
|
+
|
|
630
|
+
async def put( # type: ignore[override]
|
|
631
|
+
self,
|
|
632
|
+
url: str,
|
|
633
|
+
**kwargs: Unpack[RequestParams],
|
|
634
|
+
) -> Response:
|
|
635
|
+
"""
|
|
636
|
+
Make an async PUT request.
|
|
637
|
+
|
|
638
|
+
Args:
|
|
639
|
+
url: Request URL.
|
|
640
|
+
**kwargs: Request parameters including body options.
|
|
641
|
+
|
|
642
|
+
Returns:
|
|
643
|
+
Response object.
|
|
644
|
+
"""
|
|
645
|
+
return await self.request(method="PUT", url=url, **kwargs)
|
|
646
|
+
|
|
647
|
+
async def patch( # type: ignore[override]
|
|
648
|
+
self,
|
|
649
|
+
url: str,
|
|
650
|
+
**kwargs: Unpack[RequestParams],
|
|
651
|
+
) -> Response:
|
|
652
|
+
"""
|
|
653
|
+
Make an async PATCH request.
|
|
654
|
+
|
|
655
|
+
Args:
|
|
656
|
+
url: Request URL.
|
|
657
|
+
**kwargs: Request parameters including body options.
|
|
658
|
+
|
|
659
|
+
Returns:
|
|
660
|
+
Response object.
|
|
661
|
+
"""
|
|
662
|
+
return await self.request(method="PATCH", url=url, **kwargs)
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def request(
|
|
666
|
+
method: HttpMethod,
|
|
667
|
+
url: str,
|
|
668
|
+
verify: bool | None = True,
|
|
669
|
+
ca_cert_file: str | None = None,
|
|
670
|
+
client_pem: str | None = None,
|
|
671
|
+
**kwargs: Unpack[RequestParams],
|
|
672
|
+
) -> Response:
|
|
673
|
+
"""
|
|
674
|
+
Make an HTTP request using a temporary client.
|
|
675
|
+
|
|
676
|
+
This is a convenience function for one-off requests. For multiple requests,
|
|
677
|
+
use a Client instance for better performance (connection pooling).
|
|
678
|
+
|
|
679
|
+
Args:
|
|
680
|
+
method: HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS).
|
|
681
|
+
url: Request URL.
|
|
682
|
+
verify: Verify SSL certificates. Default is True.
|
|
683
|
+
ca_cert_file: Path to CA certificate bundle.
|
|
684
|
+
client_pem: Path to client certificate for mTLS.
|
|
685
|
+
**kwargs: Additional request parameters.
|
|
686
|
+
|
|
687
|
+
Returns:
|
|
688
|
+
Response object.
|
|
689
|
+
|
|
690
|
+
Example:
|
|
691
|
+
```python
|
|
692
|
+
import httpr
|
|
693
|
+
|
|
694
|
+
response = httpr.request("GET", "https://httpbin.org/get")
|
|
695
|
+
response = httpr.request("POST", "https://httpbin.org/post", json={"key": "value"})
|
|
696
|
+
```
|
|
697
|
+
"""
|
|
698
|
+
with Client(
|
|
699
|
+
verify=verify,
|
|
700
|
+
ca_cert_file=ca_cert_file,
|
|
701
|
+
client_pem=client_pem,
|
|
702
|
+
) as client:
|
|
703
|
+
return client.request(method, url, **kwargs)
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def get(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
707
|
+
"""
|
|
708
|
+
Make a GET request using a temporary client.
|
|
709
|
+
|
|
710
|
+
Args:
|
|
711
|
+
url: Request URL.
|
|
712
|
+
**kwargs: Request parameters (params, headers, cookies, auth, timeout, etc.).
|
|
713
|
+
|
|
714
|
+
Returns:
|
|
715
|
+
Response object.
|
|
716
|
+
|
|
717
|
+
Example:
|
|
718
|
+
```python
|
|
719
|
+
import httpr
|
|
720
|
+
|
|
721
|
+
response = httpr.get("https://httpbin.org/get", params={"key": "value"})
|
|
722
|
+
print(response.json())
|
|
723
|
+
```
|
|
724
|
+
"""
|
|
725
|
+
return request(method="GET", url=url, **kwargs)
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
def head(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
729
|
+
"""
|
|
730
|
+
Make a HEAD request using a temporary client.
|
|
731
|
+
|
|
732
|
+
Args:
|
|
733
|
+
url: Request URL.
|
|
734
|
+
**kwargs: Request parameters.
|
|
735
|
+
|
|
736
|
+
Returns:
|
|
737
|
+
Response object (body will be empty).
|
|
738
|
+
|
|
739
|
+
Example:
|
|
740
|
+
```python
|
|
741
|
+
import httpr
|
|
742
|
+
|
|
743
|
+
response = httpr.head("https://httpbin.org/get")
|
|
744
|
+
print(response.headers)
|
|
745
|
+
```
|
|
746
|
+
"""
|
|
747
|
+
return request(method="HEAD", url=url, **kwargs)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def options(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
751
|
+
"""
|
|
752
|
+
Make an OPTIONS request using a temporary client.
|
|
753
|
+
|
|
754
|
+
Args:
|
|
755
|
+
url: Request URL.
|
|
756
|
+
**kwargs: Request parameters.
|
|
757
|
+
|
|
758
|
+
Returns:
|
|
759
|
+
Response object.
|
|
760
|
+
|
|
761
|
+
Example:
|
|
762
|
+
```python
|
|
763
|
+
import httpr
|
|
764
|
+
|
|
765
|
+
response = httpr.options("https://httpbin.org/get")
|
|
766
|
+
```
|
|
767
|
+
"""
|
|
768
|
+
return request(method="OPTIONS", url=url, **kwargs)
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
def delete(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
772
|
+
"""
|
|
773
|
+
Make a DELETE request using a temporary client.
|
|
774
|
+
|
|
775
|
+
Args:
|
|
776
|
+
url: Request URL.
|
|
777
|
+
**kwargs: Request parameters.
|
|
778
|
+
|
|
779
|
+
Returns:
|
|
780
|
+
Response object.
|
|
781
|
+
|
|
782
|
+
Example:
|
|
783
|
+
```python
|
|
784
|
+
import httpr
|
|
785
|
+
|
|
786
|
+
response = httpr.delete("https://httpbin.org/delete")
|
|
787
|
+
```
|
|
788
|
+
"""
|
|
789
|
+
return request(method="DELETE", url=url, **kwargs)
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def post(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
793
|
+
"""
|
|
794
|
+
Make a POST request using a temporary client.
|
|
795
|
+
|
|
796
|
+
Args:
|
|
797
|
+
url: Request URL.
|
|
798
|
+
**kwargs: Request parameters (json, data, content, files, etc.).
|
|
799
|
+
|
|
800
|
+
Returns:
|
|
801
|
+
Response object.
|
|
802
|
+
|
|
803
|
+
Example:
|
|
804
|
+
```python
|
|
805
|
+
import httpr
|
|
806
|
+
|
|
807
|
+
# JSON body
|
|
808
|
+
response = httpr.post("https://httpbin.org/post", json={"key": "value"})
|
|
809
|
+
|
|
810
|
+
# Form data
|
|
811
|
+
response = httpr.post("https://httpbin.org/post", data={"field": "value"})
|
|
812
|
+
```
|
|
813
|
+
"""
|
|
814
|
+
return request(method="POST", url=url, **kwargs)
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
def put(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
818
|
+
"""
|
|
819
|
+
Make a PUT request using a temporary client.
|
|
820
|
+
|
|
821
|
+
Args:
|
|
822
|
+
url: Request URL.
|
|
823
|
+
**kwargs: Request parameters.
|
|
824
|
+
|
|
825
|
+
Returns:
|
|
826
|
+
Response object.
|
|
827
|
+
|
|
828
|
+
Example:
|
|
829
|
+
```python
|
|
830
|
+
import httpr
|
|
831
|
+
|
|
832
|
+
response = httpr.put("https://httpbin.org/put", json={"key": "value"})
|
|
833
|
+
```
|
|
834
|
+
"""
|
|
835
|
+
return request(method="PUT", url=url, **kwargs)
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def patch(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response:
|
|
839
|
+
"""
|
|
840
|
+
Make a PATCH request using a temporary client.
|
|
841
|
+
|
|
842
|
+
Args:
|
|
843
|
+
url: Request URL.
|
|
844
|
+
**kwargs: Request parameters.
|
|
845
|
+
|
|
846
|
+
Returns:
|
|
847
|
+
Response object.
|
|
848
|
+
|
|
849
|
+
Example:
|
|
850
|
+
```python
|
|
851
|
+
import httpr
|
|
852
|
+
|
|
853
|
+
response = httpr.patch("https://httpbin.org/patch", json={"field": "new_value"})
|
|
854
|
+
```
|
|
855
|
+
"""
|
|
856
|
+
return request(method="PATCH", url=url, **kwargs)
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
__all__ = [
|
|
860
|
+
"Client",
|
|
861
|
+
"AsyncClient",
|
|
862
|
+
"request",
|
|
863
|
+
"get",
|
|
864
|
+
"head",
|
|
865
|
+
"options",
|
|
866
|
+
"delete",
|
|
867
|
+
"post",
|
|
868
|
+
"put",
|
|
869
|
+
"patch",
|
|
870
|
+
]
|
httpr/httpr.pyd
ADDED
|
Binary file
|
httpr/httpr.pyi
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Any, Literal, TypedDict
|
|
5
|
+
|
|
6
|
+
if sys.version_info <= (3, 11):
|
|
7
|
+
from typing_extensions import Unpack
|
|
8
|
+
else:
|
|
9
|
+
from typing import Unpack
|
|
10
|
+
|
|
11
|
+
HttpMethod = Literal["GET", "HEAD", "OPTIONS", "DELETE", "POST", "PUT", "PATCH"]
|
|
12
|
+
|
|
13
|
+
class RequestParams(TypedDict, total=False):
|
|
14
|
+
auth: tuple[str, str | None] | None
|
|
15
|
+
auth_bearer: str | None
|
|
16
|
+
params: dict[str, str] | None
|
|
17
|
+
headers: dict[str, str] | None
|
|
18
|
+
cookies: dict[str, str] | None
|
|
19
|
+
timeout: float | None
|
|
20
|
+
content: bytes | None
|
|
21
|
+
data: dict[str, Any] | None
|
|
22
|
+
json: Any | None
|
|
23
|
+
files: dict[str, str] | None
|
|
24
|
+
|
|
25
|
+
class ClientRequestParams(RequestParams):
|
|
26
|
+
verify: bool | None
|
|
27
|
+
ca_cert_file: str | None
|
|
28
|
+
client_pem: str | None
|
|
29
|
+
|
|
30
|
+
class Response:
|
|
31
|
+
@property
|
|
32
|
+
def content(self) -> bytes: ...
|
|
33
|
+
@property
|
|
34
|
+
def cookies(self) -> dict[str, str]: ...
|
|
35
|
+
@property
|
|
36
|
+
def headers(self) -> dict[str, str]: ...
|
|
37
|
+
@property
|
|
38
|
+
def status_code(self) -> int: ...
|
|
39
|
+
@property
|
|
40
|
+
def url(self) -> str: ...
|
|
41
|
+
@property
|
|
42
|
+
def encoding(self) -> str: ...
|
|
43
|
+
@property
|
|
44
|
+
def text(self) -> str: ...
|
|
45
|
+
def json(self) -> Any: ...
|
|
46
|
+
@property
|
|
47
|
+
def text_markdown(self) -> str: ...
|
|
48
|
+
@property
|
|
49
|
+
def text_plain(self) -> str: ...
|
|
50
|
+
@property
|
|
51
|
+
def text_rich(self) -> str: ...
|
|
52
|
+
|
|
53
|
+
class RClient:
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
auth: tuple[str, str | None] | None = None,
|
|
57
|
+
auth_bearer: str | None = None,
|
|
58
|
+
params: dict[str, str] | None = None,
|
|
59
|
+
headers: dict[str, str] | None = None,
|
|
60
|
+
cookies: dict[str, str] | None = None,
|
|
61
|
+
timeout: float | None = None,
|
|
62
|
+
cookie_store: bool | None = True,
|
|
63
|
+
referer: bool | None = True,
|
|
64
|
+
proxy: str | None = None,
|
|
65
|
+
follow_redirects: bool | None = True,
|
|
66
|
+
max_redirects: int | None = 20,
|
|
67
|
+
verify: bool | None = True,
|
|
68
|
+
ca_cert_file: str | None = None,
|
|
69
|
+
client_pem: str | None = None,
|
|
70
|
+
https_only: bool | None = False,
|
|
71
|
+
http2_only: bool | None = False,
|
|
72
|
+
): ...
|
|
73
|
+
@property
|
|
74
|
+
def headers(self) -> dict[str, str]: ...
|
|
75
|
+
@headers.setter
|
|
76
|
+
def headers(self, headers: dict[str, str]) -> None: ...
|
|
77
|
+
@property
|
|
78
|
+
def cookies(self) -> dict[str, str]: ...
|
|
79
|
+
@cookies.setter
|
|
80
|
+
def cookies(self, cookies: dict[str, str]) -> None: ...
|
|
81
|
+
@property
|
|
82
|
+
def proxy(self) -> str | None: ...
|
|
83
|
+
@proxy.setter
|
|
84
|
+
def proxy(self, proxy: str) -> None: ...
|
|
85
|
+
def request(self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
86
|
+
def get(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
87
|
+
def head(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
88
|
+
def options(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
89
|
+
def delete(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
90
|
+
def post(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
91
|
+
def put(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
92
|
+
def patch(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
93
|
+
|
|
94
|
+
def request(method: HttpMethod, url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
95
|
+
def get(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
96
|
+
def head(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
97
|
+
def options(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
98
|
+
def delete(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
99
|
+
def post(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
100
|
+
def put(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
101
|
+
def patch(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
httpr/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: httpr
|
|
3
|
+
Version: 0.1.17
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
14
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Dist: certifi ; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=8.1.1 ; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.25.3 ; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest-httpbin>=2.1.0 ; extra == 'dev'
|
|
21
|
+
Requires-Dist: typing-extensions ; python_full_version < '3.12' and extra == 'dev'
|
|
22
|
+
Requires-Dist: mypy>=1.14.1 ; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.9.2 ; extra == 'dev'
|
|
24
|
+
Requires-Dist: maturin ; extra == 'dev'
|
|
25
|
+
Requires-Dist: trustme ; extra == 'dev'
|
|
26
|
+
Requires-Dist: mkdocs-material[imaging] ; extra == 'docs'
|
|
27
|
+
Requires-Dist: mkdocstrings[python]>=0.27.0 ; extra == 'docs'
|
|
28
|
+
Requires-Dist: mkdocs-gen-files ; extra == 'docs'
|
|
29
|
+
Requires-Dist: mkdocs-literate-nav ; extra == 'docs'
|
|
30
|
+
Requires-Dist: httpr[dev] ; extra == 'scratch'
|
|
31
|
+
Requires-Dist: matplotlib ; extra == 'scratch'
|
|
32
|
+
Requires-Dist: pandas ; extra == 'scratch'
|
|
33
|
+
Requires-Dist: jupyter ; extra == 'scratch'
|
|
34
|
+
Requires-Dist: ipykernel ; extra == 'scratch'
|
|
35
|
+
Requires-Dist: httpx ; extra == 'scratch'
|
|
36
|
+
Requires-Dist: gunicorn ; extra == 'scratch'
|
|
37
|
+
Requires-Dist: uvicorn ; extra == 'scratch'
|
|
38
|
+
Requires-Dist: trustme ; extra == 'scratch'
|
|
39
|
+
Requires-Dist: starlette ; extra == 'scratch'
|
|
40
|
+
Requires-Dist: fastapi ; extra == 'scratch'
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Provides-Extra: docs
|
|
43
|
+
Provides-Extra: scratch
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Summary: Fast HTTP client for Python
|
|
46
|
+
Keywords: python,request
|
|
47
|
+
Author: thomasht86
|
|
48
|
+
License: MIT License
|
|
49
|
+
Requires-Python: >=3.9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
httpr-0.1.17.dist-info/METADATA,sha256=W9D8erBK9zt9tqon55skX41ATkiwcseTJG9idOwGbsk,2129
|
|
2
|
+
httpr-0.1.17.dist-info/WHEEL,sha256=W8IbRrW6aFuwgkpVWKTtkIq8XwJIIpO5tHf4goK_jm8,95
|
|
3
|
+
httpr-0.1.17.dist-info/licenses/LICENSE,sha256=O15TIxUAXq6sSpPu0K3CJu_dT5ZzCgIk7hQtZsf0lEk,1084
|
|
4
|
+
httpr/__init__.py,sha256=TQtmQx9A8g9mEHMghynFab2XC-bjmu1fK1FMjrYNJ18,25174
|
|
5
|
+
httpr/httpr.pyd,sha256=k87zTK5grPYfqo18BiJEvdTW8vfwhw2-NybbI_tFwss,4539904
|
|
6
|
+
httpr/httpr.pyi,sha256=VbROFo3ZXTacg2Fe0kvQWZ0RXXrAK08F4ivUL0cvGtY,3830
|
|
7
|
+
httpr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
httpr-0.1.17.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 deedy5
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|