httpr 0.3.2__cp39-abi3-macosx_10_12_x86_64.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 +1079 -0
- httpr/httpr.abi3.so +0 -0
- httpr/httpr.pyi +706 -0
- httpr/py.typed +0 -0
- httpr-0.3.2.dist-info/METADATA +481 -0
- httpr-0.3.2.dist-info/RECORD +8 -0
- httpr-0.3.2.dist-info/WHEEL +4 -0
- httpr-0.3.2.dist-info/licenses/LICENSE +21 -0
httpr/httpr.abi3.so
ADDED
|
Binary file
|
httpr/httpr.pyi
ADDED
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from collections.abc import Iterator
|
|
5
|
+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
6
|
+
from typing import Any, Literal, TypedDict
|
|
7
|
+
|
|
8
|
+
if sys.version_info <= (3, 11):
|
|
9
|
+
from typing_extensions import Unpack
|
|
10
|
+
else:
|
|
11
|
+
from typing import Unpack
|
|
12
|
+
|
|
13
|
+
HttpMethod = Literal["GET", "HEAD", "OPTIONS", "DELETE", "POST", "PUT", "PATCH"]
|
|
14
|
+
|
|
15
|
+
class RequestParams(TypedDict, total=False):
|
|
16
|
+
auth: tuple[str, str | None] | None
|
|
17
|
+
auth_bearer: str | None
|
|
18
|
+
params: dict[str, str] | None
|
|
19
|
+
headers: dict[str, str] | None
|
|
20
|
+
cookies: dict[str, str] | None
|
|
21
|
+
timeout: float | None
|
|
22
|
+
content: bytes | None
|
|
23
|
+
data: dict[str, Any] | None
|
|
24
|
+
json: Any | None
|
|
25
|
+
files: dict[str, str] | None
|
|
26
|
+
|
|
27
|
+
class ClientRequestParams(RequestParams):
|
|
28
|
+
verify: bool | None
|
|
29
|
+
ca_cert_file: str | None
|
|
30
|
+
client_pem: str | None
|
|
31
|
+
client_pem_data: bytes | None
|
|
32
|
+
|
|
33
|
+
class CaseInsensitiveHeaderMap:
|
|
34
|
+
"""
|
|
35
|
+
A case-insensitive dictionary-like class for HTTP headers.
|
|
36
|
+
|
|
37
|
+
HTTP headers are case-insensitive per the HTTP specification.
|
|
38
|
+
This class allows accessing headers using any case while preserving
|
|
39
|
+
the original case for iteration.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
```python
|
|
43
|
+
headers = response.headers
|
|
44
|
+
content_type = headers["Content-Type"] # Works
|
|
45
|
+
content_type = headers["content-type"] # Also works
|
|
46
|
+
|
|
47
|
+
if "Content-Type" in headers:
|
|
48
|
+
print("Has content type")
|
|
49
|
+
|
|
50
|
+
for key, value in headers.items():
|
|
51
|
+
print(f"{key}: {value}")
|
|
52
|
+
```
|
|
53
|
+
"""
|
|
54
|
+
def __getitem__(self, key: str) -> str:
|
|
55
|
+
"""Get a header value by name (case-insensitive)."""
|
|
56
|
+
...
|
|
57
|
+
def __contains__(self, key: str) -> bool:
|
|
58
|
+
"""Check if a header exists (case-insensitive)."""
|
|
59
|
+
...
|
|
60
|
+
def __iter__(self) -> Iterator[str]:
|
|
61
|
+
"""Iterate over header names."""
|
|
62
|
+
...
|
|
63
|
+
def items(self) -> list[tuple[str, str]]:
|
|
64
|
+
"""Return a list of (name, value) tuples."""
|
|
65
|
+
...
|
|
66
|
+
def keys(self) -> list[str]:
|
|
67
|
+
"""Return a list of header names."""
|
|
68
|
+
...
|
|
69
|
+
def values(self) -> list[str]:
|
|
70
|
+
"""Return a list of header values."""
|
|
71
|
+
...
|
|
72
|
+
def get(self, key: str, default: str | None = None) -> str:
|
|
73
|
+
"""
|
|
74
|
+
Get a header value by name (case-insensitive).
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
key: Header name to look up.
|
|
78
|
+
default: Value to return if header is not found. Defaults to None.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
The header value, or the default if not found.
|
|
82
|
+
"""
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
class Response:
|
|
86
|
+
"""
|
|
87
|
+
An HTTP response object.
|
|
88
|
+
|
|
89
|
+
This class provides access to the response status, headers, cookies,
|
|
90
|
+
and body content. The body can be accessed as bytes, text, JSON, or CBOR.
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
```python
|
|
94
|
+
response = client.get("https://httpbin.org/get")
|
|
95
|
+
|
|
96
|
+
# Status
|
|
97
|
+
print(response.status_code) # 200
|
|
98
|
+
print(response.url) # Final URL after redirects
|
|
99
|
+
|
|
100
|
+
# Headers (case-insensitive access)
|
|
101
|
+
print(response.headers["content-type"])
|
|
102
|
+
|
|
103
|
+
# Body
|
|
104
|
+
print(response.text) # Decoded text
|
|
105
|
+
print(response.json()) # Parsed JSON
|
|
106
|
+
print(response.content) # Raw bytes
|
|
107
|
+
```
|
|
108
|
+
"""
|
|
109
|
+
@property
|
|
110
|
+
def content(self) -> bytes:
|
|
111
|
+
"""Raw response body as bytes."""
|
|
112
|
+
...
|
|
113
|
+
@property
|
|
114
|
+
def cookies(self) -> dict[str, str]:
|
|
115
|
+
"""Response cookies as a dictionary."""
|
|
116
|
+
...
|
|
117
|
+
@property
|
|
118
|
+
def headers(self) -> CaseInsensitiveHeaderMap:
|
|
119
|
+
"""
|
|
120
|
+
Response headers as a case-insensitive dictionary-like object.
|
|
121
|
+
|
|
122
|
+
Headers can be accessed using any case (e.g., "Content-Type" or "content-type").
|
|
123
|
+
"""
|
|
124
|
+
...
|
|
125
|
+
@property
|
|
126
|
+
def status_code(self) -> int:
|
|
127
|
+
"""HTTP status code (e.g., 200, 404, 500)."""
|
|
128
|
+
...
|
|
129
|
+
@property
|
|
130
|
+
def url(self) -> str:
|
|
131
|
+
"""Final URL after any redirects."""
|
|
132
|
+
...
|
|
133
|
+
@property
|
|
134
|
+
def encoding(self) -> str:
|
|
135
|
+
"""
|
|
136
|
+
Character encoding of the response.
|
|
137
|
+
|
|
138
|
+
Detected from Content-Type header or response body.
|
|
139
|
+
Can be set to override auto-detection.
|
|
140
|
+
"""
|
|
141
|
+
...
|
|
142
|
+
@encoding.setter
|
|
143
|
+
def encoding(self, value: str) -> None: ...
|
|
144
|
+
@property
|
|
145
|
+
def text(self) -> str:
|
|
146
|
+
"""Response body decoded as text using the detected encoding."""
|
|
147
|
+
...
|
|
148
|
+
def json(self) -> Any:
|
|
149
|
+
"""
|
|
150
|
+
Parse response body as JSON.
|
|
151
|
+
|
|
152
|
+
If Content-Type is application/cbor, automatically deserializes as CBOR.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Parsed JSON/CBOR data as Python objects.
|
|
156
|
+
"""
|
|
157
|
+
...
|
|
158
|
+
def cbor(self) -> Any:
|
|
159
|
+
"""
|
|
160
|
+
Parse response body as CBOR (Concise Binary Object Representation).
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Parsed CBOR data as Python objects.
|
|
164
|
+
"""
|
|
165
|
+
...
|
|
166
|
+
@property
|
|
167
|
+
def text_markdown(self) -> str:
|
|
168
|
+
"""
|
|
169
|
+
Response body converted from HTML to Markdown format.
|
|
170
|
+
|
|
171
|
+
Useful for reading HTML content as plain text.
|
|
172
|
+
"""
|
|
173
|
+
...
|
|
174
|
+
@property
|
|
175
|
+
def text_plain(self) -> str:
|
|
176
|
+
"""
|
|
177
|
+
Response body converted from HTML to plain text.
|
|
178
|
+
|
|
179
|
+
Strips all formatting and returns only the text content.
|
|
180
|
+
"""
|
|
181
|
+
...
|
|
182
|
+
@property
|
|
183
|
+
def text_rich(self) -> str:
|
|
184
|
+
"""
|
|
185
|
+
Response body converted from HTML to rich text format.
|
|
186
|
+
|
|
187
|
+
Preserves some formatting using Unicode characters.
|
|
188
|
+
"""
|
|
189
|
+
...
|
|
190
|
+
|
|
191
|
+
class TextIterator:
|
|
192
|
+
"""Iterator for text chunks from a streaming response."""
|
|
193
|
+
def __iter__(self) -> TextIterator: ...
|
|
194
|
+
def __next__(self) -> str: ...
|
|
195
|
+
|
|
196
|
+
class LineIterator:
|
|
197
|
+
"""Iterator for lines from a streaming response."""
|
|
198
|
+
def __iter__(self) -> LineIterator: ...
|
|
199
|
+
def __next__(self) -> str: ...
|
|
200
|
+
|
|
201
|
+
class StreamingResponse:
|
|
202
|
+
"""
|
|
203
|
+
A streaming HTTP response that allows iterating over chunks of data.
|
|
204
|
+
|
|
205
|
+
This class provides methods to iterate over the response body in chunks
|
|
206
|
+
without buffering the entire response in memory.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def cookies(self) -> dict[str, str]:
|
|
211
|
+
"""Response cookies."""
|
|
212
|
+
...
|
|
213
|
+
@property
|
|
214
|
+
def headers(self) -> CaseInsensitiveHeaderMap:
|
|
215
|
+
"""Response headers (case-insensitive access)."""
|
|
216
|
+
...
|
|
217
|
+
@property
|
|
218
|
+
def status_code(self) -> int:
|
|
219
|
+
"""HTTP status code."""
|
|
220
|
+
...
|
|
221
|
+
@property
|
|
222
|
+
def url(self) -> str:
|
|
223
|
+
"""Final URL after any redirects."""
|
|
224
|
+
...
|
|
225
|
+
@property
|
|
226
|
+
def is_closed(self) -> bool:
|
|
227
|
+
"""Whether the stream has been closed."""
|
|
228
|
+
...
|
|
229
|
+
@property
|
|
230
|
+
def is_consumed(self) -> bool:
|
|
231
|
+
"""Whether the stream has been fully consumed."""
|
|
232
|
+
...
|
|
233
|
+
def __iter__(self) -> Iterator[bytes]:
|
|
234
|
+
"""Iterate over the response body as bytes chunks."""
|
|
235
|
+
...
|
|
236
|
+
def __next__(self) -> bytes:
|
|
237
|
+
"""Get the next chunk of bytes."""
|
|
238
|
+
...
|
|
239
|
+
def iter_bytes(self) -> Iterator[bytes]:
|
|
240
|
+
"""
|
|
241
|
+
Iterate over the response body as bytes chunks.
|
|
242
|
+
|
|
243
|
+
Yields chunks of bytes as they are received from the server.
|
|
244
|
+
"""
|
|
245
|
+
...
|
|
246
|
+
def iter_text(self) -> TextIterator:
|
|
247
|
+
"""
|
|
248
|
+
Iterate over the response body as text chunks.
|
|
249
|
+
|
|
250
|
+
Decodes each chunk using the response's encoding.
|
|
251
|
+
"""
|
|
252
|
+
...
|
|
253
|
+
def iter_lines(self) -> LineIterator:
|
|
254
|
+
"""
|
|
255
|
+
Iterate over the response body line by line.
|
|
256
|
+
|
|
257
|
+
Yields complete lines including newline characters.
|
|
258
|
+
"""
|
|
259
|
+
...
|
|
260
|
+
def read(self) -> bytes:
|
|
261
|
+
"""
|
|
262
|
+
Read the entire remaining response body into memory.
|
|
263
|
+
|
|
264
|
+
This consumes the stream.
|
|
265
|
+
"""
|
|
266
|
+
...
|
|
267
|
+
def close(self) -> None:
|
|
268
|
+
"""
|
|
269
|
+
Close the streaming response and release resources.
|
|
270
|
+
"""
|
|
271
|
+
...
|
|
272
|
+
|
|
273
|
+
class RClient:
|
|
274
|
+
def __init__(
|
|
275
|
+
self,
|
|
276
|
+
auth: tuple[str, str | None] | None = None,
|
|
277
|
+
auth_bearer: str | None = None,
|
|
278
|
+
params: dict[str, str] | None = None,
|
|
279
|
+
headers: dict[str, str] | None = None,
|
|
280
|
+
cookies: dict[str, str] | None = None,
|
|
281
|
+
timeout: float | None = None,
|
|
282
|
+
cookie_store: bool | None = True,
|
|
283
|
+
referer: bool | None = True,
|
|
284
|
+
proxy: str | None = None,
|
|
285
|
+
follow_redirects: bool | None = True,
|
|
286
|
+
max_redirects: int | None = 20,
|
|
287
|
+
verify: bool | None = True,
|
|
288
|
+
ca_cert_file: str | None = None,
|
|
289
|
+
client_pem: str | None = None,
|
|
290
|
+
client_pem_data: bytes | None = None,
|
|
291
|
+
https_only: bool | None = False,
|
|
292
|
+
http2_only: bool | None = False,
|
|
293
|
+
): ...
|
|
294
|
+
@property
|
|
295
|
+
def headers(self) -> dict[str, str]: ...
|
|
296
|
+
@headers.setter
|
|
297
|
+
def headers(self, headers: dict[str, str] | None) -> None: ...
|
|
298
|
+
@property
|
|
299
|
+
def cookies(self) -> dict[str, str]: ...
|
|
300
|
+
@cookies.setter
|
|
301
|
+
def cookies(self, cookies: dict[str, str] | None) -> None: ...
|
|
302
|
+
@property
|
|
303
|
+
def proxy(self) -> str | None: ...
|
|
304
|
+
@proxy.setter
|
|
305
|
+
def proxy(self, proxy: str) -> None: ...
|
|
306
|
+
@property
|
|
307
|
+
def auth(self) -> tuple[str, str | None] | None: ...
|
|
308
|
+
@auth.setter
|
|
309
|
+
def auth(self, auth: tuple[str, str | None] | None) -> None: ...
|
|
310
|
+
@property
|
|
311
|
+
def auth_bearer(self) -> str | None: ...
|
|
312
|
+
@auth_bearer.setter
|
|
313
|
+
def auth_bearer(self, auth_bearer: str | None) -> None: ...
|
|
314
|
+
@property
|
|
315
|
+
def params(self) -> dict[str, str] | None: ...
|
|
316
|
+
@params.setter
|
|
317
|
+
def params(self, params: dict[str, str] | None) -> None: ...
|
|
318
|
+
@property
|
|
319
|
+
def timeout(self) -> float | None: ...
|
|
320
|
+
@timeout.setter
|
|
321
|
+
def timeout(self, timeout: float | None) -> None: ...
|
|
322
|
+
def request(self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
323
|
+
def _stream(self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]) -> StreamingResponse: ...
|
|
324
|
+
def get(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
325
|
+
def head(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
326
|
+
def options(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
327
|
+
def delete(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
328
|
+
def post(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
329
|
+
def put(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
330
|
+
def patch(self, url: str, **kwargs: Unpack[RequestParams]) -> Response: ...
|
|
331
|
+
|
|
332
|
+
class Client(RClient):
|
|
333
|
+
"""
|
|
334
|
+
A synchronous HTTP client with connection pooling.
|
|
335
|
+
|
|
336
|
+
The Client class provides a high-level interface for making HTTP requests.
|
|
337
|
+
It supports connection pooling, automatic cookie handling, and various
|
|
338
|
+
authentication methods.
|
|
339
|
+
|
|
340
|
+
Example:
|
|
341
|
+
```python
|
|
342
|
+
import httpr
|
|
343
|
+
|
|
344
|
+
# Using context manager (recommended)
|
|
345
|
+
with httpr.Client() as client:
|
|
346
|
+
response = client.get("https://httpbin.org/get")
|
|
347
|
+
print(response.json())
|
|
348
|
+
|
|
349
|
+
# Or manually
|
|
350
|
+
client = httpr.Client()
|
|
351
|
+
response = client.get("https://httpbin.org/get")
|
|
352
|
+
client.close()
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Attributes:
|
|
356
|
+
headers: Default headers sent with all requests. Excludes Cookie header.
|
|
357
|
+
cookies: Default cookies sent with all requests.
|
|
358
|
+
auth: Basic auth credentials as (username, password) tuple.
|
|
359
|
+
params: Default query parameters added to all requests.
|
|
360
|
+
timeout: Default timeout in seconds.
|
|
361
|
+
proxy: Proxy URL for requests.
|
|
362
|
+
"""
|
|
363
|
+
def __init__(
|
|
364
|
+
self,
|
|
365
|
+
auth: tuple[str, str | None] | None = None,
|
|
366
|
+
auth_bearer: str | None = None,
|
|
367
|
+
params: dict[str, str] | None = None,
|
|
368
|
+
headers: dict[str, str] | None = None,
|
|
369
|
+
cookies: dict[str, str] | None = None,
|
|
370
|
+
cookie_store: bool | None = True,
|
|
371
|
+
referer: bool | None = True,
|
|
372
|
+
proxy: str | None = None,
|
|
373
|
+
timeout: float | None = 30,
|
|
374
|
+
follow_redirects: bool | None = True,
|
|
375
|
+
max_redirects: int | None = 20,
|
|
376
|
+
verify: bool | None = True,
|
|
377
|
+
ca_cert_file: str | None = None,
|
|
378
|
+
client_pem: str | None = None,
|
|
379
|
+
client_pem_data: bytes | None = None,
|
|
380
|
+
https_only: bool | None = False,
|
|
381
|
+
http2_only: bool | None = False,
|
|
382
|
+
) -> None:
|
|
383
|
+
"""
|
|
384
|
+
Initialize an HTTP client.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
auth: Basic auth credentials as (username, password). Password can be None.
|
|
388
|
+
auth_bearer: Bearer token for Authorization header.
|
|
389
|
+
params: Default query parameters to include in all requests.
|
|
390
|
+
headers: Default headers to send with all requests.
|
|
391
|
+
cookies: Default cookies to send with all requests.
|
|
392
|
+
cookie_store: Enable persistent cookie store. Default is True.
|
|
393
|
+
referer: Automatically set Referer header. Default is True.
|
|
394
|
+
proxy: Proxy URL (e.g., "http://proxy:8080" or "socks5://127.0.0.1:1080").
|
|
395
|
+
timeout: Request timeout in seconds. Default is 30.
|
|
396
|
+
follow_redirects: Follow HTTP redirects. Default is True.
|
|
397
|
+
max_redirects: Maximum redirects to follow. Default is 20.
|
|
398
|
+
verify: Verify SSL certificates. Default is True.
|
|
399
|
+
ca_cert_file: Path to CA certificate bundle (PEM format).
|
|
400
|
+
client_pem: Path to client certificate for mTLS (PEM format).
|
|
401
|
+
client_pem_data: Client certificate and key as bytes for mTLS (PEM format).
|
|
402
|
+
https_only: Only allow HTTPS requests. Default is False.
|
|
403
|
+
http2_only: Use HTTP/2 only. Default is False.
|
|
404
|
+
"""
|
|
405
|
+
...
|
|
406
|
+
def __enter__(self) -> Client: ...
|
|
407
|
+
def __exit__(self, *args: Any) -> None: ...
|
|
408
|
+
def close(self) -> None:
|
|
409
|
+
"""Close the client and release resources."""
|
|
410
|
+
...
|
|
411
|
+
def stream(
|
|
412
|
+
self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]
|
|
413
|
+
) -> AbstractContextManager[StreamingResponse]:
|
|
414
|
+
"""
|
|
415
|
+
Make a streaming HTTP request.
|
|
416
|
+
|
|
417
|
+
Returns a context manager that yields a StreamingResponse for iterating
|
|
418
|
+
over the response body in chunks.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
method: HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS).
|
|
422
|
+
url: Request URL.
|
|
423
|
+
**kwargs: Request parameters.
|
|
424
|
+
|
|
425
|
+
Yields:
|
|
426
|
+
StreamingResponse: A response object that can be iterated.
|
|
427
|
+
|
|
428
|
+
Example:
|
|
429
|
+
```python
|
|
430
|
+
with client.stream("GET", "https://example.com/large-file") as response:
|
|
431
|
+
for chunk in response.iter_bytes():
|
|
432
|
+
process(chunk)
|
|
433
|
+
```
|
|
434
|
+
"""
|
|
435
|
+
...
|
|
436
|
+
|
|
437
|
+
class AsyncClient(Client):
|
|
438
|
+
"""
|
|
439
|
+
An asynchronous HTTP client for use with asyncio.
|
|
440
|
+
|
|
441
|
+
AsyncClient wraps the synchronous Client using asyncio.run_in_executor(),
|
|
442
|
+
providing an async interface while leveraging the Rust implementation's
|
|
443
|
+
performance.
|
|
444
|
+
|
|
445
|
+
Example:
|
|
446
|
+
```python
|
|
447
|
+
import asyncio
|
|
448
|
+
import httpr
|
|
449
|
+
|
|
450
|
+
async def main():
|
|
451
|
+
async with httpr.AsyncClient() as client:
|
|
452
|
+
response = await client.get("https://httpbin.org/get")
|
|
453
|
+
print(response.json())
|
|
454
|
+
|
|
455
|
+
asyncio.run(main())
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Note:
|
|
459
|
+
AsyncClient runs synchronous Rust code in a thread executor.
|
|
460
|
+
It provides concurrency benefits for I/O-bound tasks but is not
|
|
461
|
+
native async I/O.
|
|
462
|
+
"""
|
|
463
|
+
def __init__(
|
|
464
|
+
self,
|
|
465
|
+
auth: tuple[str, str | None] | None = None,
|
|
466
|
+
auth_bearer: str | None = None,
|
|
467
|
+
params: dict[str, str] | None = None,
|
|
468
|
+
headers: dict[str, str] | None = None,
|
|
469
|
+
cookies: dict[str, str] | None = None,
|
|
470
|
+
cookie_store: bool | None = True,
|
|
471
|
+
referer: bool | None = True,
|
|
472
|
+
proxy: str | None = None,
|
|
473
|
+
timeout: float | None = 30,
|
|
474
|
+
follow_redirects: bool | None = True,
|
|
475
|
+
max_redirects: int | None = 20,
|
|
476
|
+
verify: bool | None = True,
|
|
477
|
+
ca_cert_file: str | None = None,
|
|
478
|
+
client_pem: str | None = None,
|
|
479
|
+
client_pem_data: bytes | None = None,
|
|
480
|
+
https_only: bool | None = False,
|
|
481
|
+
http2_only: bool | None = False,
|
|
482
|
+
) -> None:
|
|
483
|
+
"""Initialize an async HTTP client. Accepts the same parameters as Client."""
|
|
484
|
+
...
|
|
485
|
+
async def __aenter__(self) -> AsyncClient: ...
|
|
486
|
+
async def __aexit__(self, *args: Any) -> None: ...
|
|
487
|
+
async def aclose(self) -> None:
|
|
488
|
+
"""Close the async client."""
|
|
489
|
+
...
|
|
490
|
+
async def request( # type: ignore[override]
|
|
491
|
+
self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]
|
|
492
|
+
) -> Response:
|
|
493
|
+
"""Make an async HTTP request."""
|
|
494
|
+
...
|
|
495
|
+
async def get( # type: ignore[override]
|
|
496
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
497
|
+
) -> Response:
|
|
498
|
+
"""Make an async GET request."""
|
|
499
|
+
...
|
|
500
|
+
async def head( # type: ignore[override]
|
|
501
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
502
|
+
) -> Response:
|
|
503
|
+
"""Make an async HEAD request."""
|
|
504
|
+
...
|
|
505
|
+
async def options( # type: ignore[override]
|
|
506
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
507
|
+
) -> Response:
|
|
508
|
+
"""Make an async OPTIONS request."""
|
|
509
|
+
...
|
|
510
|
+
async def delete( # type: ignore[override]
|
|
511
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
512
|
+
) -> Response:
|
|
513
|
+
"""Make an async DELETE request."""
|
|
514
|
+
...
|
|
515
|
+
async def post( # type: ignore[override]
|
|
516
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
517
|
+
) -> Response:
|
|
518
|
+
"""Make an async POST request."""
|
|
519
|
+
...
|
|
520
|
+
async def put( # type: ignore[override]
|
|
521
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
522
|
+
) -> Response:
|
|
523
|
+
"""Make an async PUT request."""
|
|
524
|
+
...
|
|
525
|
+
async def patch( # type: ignore[override]
|
|
526
|
+
self, url: str, **kwargs: Unpack[RequestParams]
|
|
527
|
+
) -> Response:
|
|
528
|
+
"""Make an async PATCH request."""
|
|
529
|
+
...
|
|
530
|
+
def stream( # type: ignore[override]
|
|
531
|
+
self, method: HttpMethod, url: str, **kwargs: Unpack[RequestParams]
|
|
532
|
+
) -> AbstractAsyncContextManager[StreamingResponse]:
|
|
533
|
+
"""
|
|
534
|
+
Make an async streaming HTTP request.
|
|
535
|
+
|
|
536
|
+
Returns an async context manager that yields a StreamingResponse.
|
|
537
|
+
|
|
538
|
+
Example:
|
|
539
|
+
```python
|
|
540
|
+
async with client.stream("GET", "https://example.com/large-file") as response:
|
|
541
|
+
for chunk in response.iter_bytes():
|
|
542
|
+
process(chunk)
|
|
543
|
+
```
|
|
544
|
+
"""
|
|
545
|
+
...
|
|
546
|
+
|
|
547
|
+
def request(method: HttpMethod, url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
548
|
+
def get(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
549
|
+
def head(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
550
|
+
def options(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
551
|
+
def delete(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
552
|
+
def post(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
553
|
+
def put(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
554
|
+
def patch(url: str, **kwargs: Unpack[ClientRequestParams]) -> Response: ...
|
|
555
|
+
|
|
556
|
+
# Exception hierarchy - Base exceptions
|
|
557
|
+
class HTTPError(Exception):
|
|
558
|
+
"""Base class for all httpr exceptions."""
|
|
559
|
+
|
|
560
|
+
class RequestError(HTTPError):
|
|
561
|
+
"""Base class for all exceptions that may occur when issuing a .request()."""
|
|
562
|
+
|
|
563
|
+
class TransportError(RequestError):
|
|
564
|
+
"""Base class for all exceptions that occur at the level of the Transport API."""
|
|
565
|
+
|
|
566
|
+
class NetworkError(TransportError):
|
|
567
|
+
"""The base class for network-related errors."""
|
|
568
|
+
|
|
569
|
+
class TimeoutException(TransportError):
|
|
570
|
+
"""The base class for timeout errors."""
|
|
571
|
+
|
|
572
|
+
class ProtocolError(TransportError):
|
|
573
|
+
"""The protocol was violated."""
|
|
574
|
+
|
|
575
|
+
class StreamError(Exception):
|
|
576
|
+
"""The base class for stream exceptions."""
|
|
577
|
+
|
|
578
|
+
# Timeout exceptions
|
|
579
|
+
class ConnectTimeout(TimeoutException):
|
|
580
|
+
"""Timed out while connecting to the host."""
|
|
581
|
+
|
|
582
|
+
class ReadTimeout(TimeoutException):
|
|
583
|
+
"""Timed out while receiving data from the host."""
|
|
584
|
+
|
|
585
|
+
class WriteTimeout(TimeoutException):
|
|
586
|
+
"""Timed out while sending data to the host."""
|
|
587
|
+
|
|
588
|
+
class PoolTimeout(TimeoutException):
|
|
589
|
+
"""Timed out waiting to acquire a connection from the pool."""
|
|
590
|
+
|
|
591
|
+
# Network exceptions
|
|
592
|
+
class ConnectError(NetworkError):
|
|
593
|
+
"""Failed to establish a connection."""
|
|
594
|
+
|
|
595
|
+
class ReadError(NetworkError):
|
|
596
|
+
"""Failed to receive data from the network."""
|
|
597
|
+
|
|
598
|
+
class WriteError(NetworkError):
|
|
599
|
+
"""Failed to send data through the network."""
|
|
600
|
+
|
|
601
|
+
class CloseError(NetworkError):
|
|
602
|
+
"""Failed to close a connection."""
|
|
603
|
+
|
|
604
|
+
# Protocol exceptions
|
|
605
|
+
class LocalProtocolError(ProtocolError):
|
|
606
|
+
"""A protocol was violated by the client."""
|
|
607
|
+
|
|
608
|
+
class RemoteProtocolError(ProtocolError):
|
|
609
|
+
"""The protocol was violated by the server."""
|
|
610
|
+
|
|
611
|
+
# Other transport/request exceptions
|
|
612
|
+
class UnsupportedProtocol(TransportError):
|
|
613
|
+
"""Attempted to make a request to an unsupported protocol."""
|
|
614
|
+
|
|
615
|
+
class ProxyError(TransportError):
|
|
616
|
+
"""An error occurred while establishing a proxy connection."""
|
|
617
|
+
|
|
618
|
+
class TooManyRedirects(RequestError):
|
|
619
|
+
"""Too many redirects."""
|
|
620
|
+
|
|
621
|
+
class HTTPStatusError(HTTPError):
|
|
622
|
+
"""The response had an error HTTP status of 4xx or 5xx."""
|
|
623
|
+
|
|
624
|
+
class DecodingError(RequestError):
|
|
625
|
+
"""Decoding of the response failed, due to a malformed encoding."""
|
|
626
|
+
|
|
627
|
+
# Stream exceptions
|
|
628
|
+
class StreamConsumed(StreamError):
|
|
629
|
+
"""Attempted to read or stream content, but the content has already been consumed."""
|
|
630
|
+
|
|
631
|
+
class ResponseNotRead(StreamError):
|
|
632
|
+
"""Attempted to access streaming response content, without having called read()."""
|
|
633
|
+
|
|
634
|
+
class RequestNotRead(StreamError):
|
|
635
|
+
"""Attempted to access streaming request content, without having called read()."""
|
|
636
|
+
|
|
637
|
+
class StreamClosed(StreamError):
|
|
638
|
+
"""Attempted to read or stream response content, but the request has been closed."""
|
|
639
|
+
|
|
640
|
+
# Other exceptions
|
|
641
|
+
class InvalidURL(Exception):
|
|
642
|
+
"""URL is improperly formed or cannot be parsed."""
|
|
643
|
+
|
|
644
|
+
class CookieConflict(Exception):
|
|
645
|
+
"""Attempted to lookup a cookie by name, but multiple cookies existed."""
|
|
646
|
+
|
|
647
|
+
__all__ = [
|
|
648
|
+
# Type aliases
|
|
649
|
+
"HttpMethod",
|
|
650
|
+
"RequestParams",
|
|
651
|
+
"ClientRequestParams",
|
|
652
|
+
# Response types
|
|
653
|
+
"Response",
|
|
654
|
+
"StreamingResponse",
|
|
655
|
+
"CaseInsensitiveHeaderMap",
|
|
656
|
+
"TextIterator",
|
|
657
|
+
"LineIterator",
|
|
658
|
+
# Client classes
|
|
659
|
+
"RClient",
|
|
660
|
+
"Client",
|
|
661
|
+
"AsyncClient",
|
|
662
|
+
# Module-level functions
|
|
663
|
+
"request",
|
|
664
|
+
"get",
|
|
665
|
+
"head",
|
|
666
|
+
"options",
|
|
667
|
+
"delete",
|
|
668
|
+
"post",
|
|
669
|
+
"put",
|
|
670
|
+
"patch",
|
|
671
|
+
# Base exceptions
|
|
672
|
+
"HTTPError",
|
|
673
|
+
"RequestError",
|
|
674
|
+
"TransportError",
|
|
675
|
+
"NetworkError",
|
|
676
|
+
"TimeoutException",
|
|
677
|
+
"ProtocolError",
|
|
678
|
+
"StreamError",
|
|
679
|
+
# Timeout exceptions
|
|
680
|
+
"ConnectTimeout",
|
|
681
|
+
"ReadTimeout",
|
|
682
|
+
"WriteTimeout",
|
|
683
|
+
"PoolTimeout",
|
|
684
|
+
# Network exceptions
|
|
685
|
+
"ConnectError",
|
|
686
|
+
"ReadError",
|
|
687
|
+
"WriteError",
|
|
688
|
+
"CloseError",
|
|
689
|
+
# Protocol exceptions
|
|
690
|
+
"LocalProtocolError",
|
|
691
|
+
"RemoteProtocolError",
|
|
692
|
+
# Other transport/request exceptions
|
|
693
|
+
"UnsupportedProtocol",
|
|
694
|
+
"ProxyError",
|
|
695
|
+
"TooManyRedirects",
|
|
696
|
+
"HTTPStatusError",
|
|
697
|
+
"DecodingError",
|
|
698
|
+
# Stream exceptions
|
|
699
|
+
"StreamConsumed",
|
|
700
|
+
"ResponseNotRead",
|
|
701
|
+
"RequestNotRead",
|
|
702
|
+
"StreamClosed",
|
|
703
|
+
# Other exceptions
|
|
704
|
+
"InvalidURL",
|
|
705
|
+
"CookieConflict",
|
|
706
|
+
]
|
httpr/py.typed
ADDED
|
File without changes
|