httpr 0.2.6__cp313-cp313t-win32.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.
@@ -0,0 +1,418 @@
1
+ Metadata-Version: 2.4
2
+ Name: httpr
3
+ Version: 0.2.6
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3 :: Only
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: Implementation :: CPython
12
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
13
+ Classifier: Topic :: Internet :: WWW/HTTP
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Dist: certifi ; extra == 'dev'
16
+ Requires-Dist: pytest>=8.1.1 ; extra == 'dev'
17
+ Requires-Dist: pytest-asyncio>=0.25.3 ; extra == 'dev'
18
+ Requires-Dist: pytest-httpbin>=2.1.0 ; extra == 'dev'
19
+ Requires-Dist: typing-extensions ; python_full_version < '3.12' and extra == 'dev'
20
+ Requires-Dist: mypy>=1.14.1 ; extra == 'dev'
21
+ Requires-Dist: ruff>=0.9.2 ; extra == 'dev'
22
+ Requires-Dist: maturin ; extra == 'dev'
23
+ Requires-Dist: trustme ; extra == 'dev'
24
+ Requires-Dist: cbor2 ; extra == 'dev'
25
+ Requires-Dist: mkdocs-material[imaging] ; extra == 'docs'
26
+ Requires-Dist: mkdocstrings[python]>=0.27.0 ; extra == 'docs'
27
+ Requires-Dist: mkdocs-gen-files ; extra == 'docs'
28
+ Requires-Dist: mkdocs-literate-nav ; extra == 'docs'
29
+ Requires-Dist: mkdocs-llmstxt ; extra == 'docs'
30
+ Requires-Dist: matplotlib ; extra == 'benchmark'
31
+ Requires-Dist: pandas ; extra == 'benchmark'
32
+ Requires-Dist: starlette ; extra == 'benchmark'
33
+ Requires-Dist: uvicorn ; extra == 'benchmark'
34
+ Requires-Dist: requests ; extra == 'benchmark'
35
+ Requires-Dist: httpx ; extra == 'benchmark'
36
+ Requires-Dist: tls-client ; extra == 'benchmark'
37
+ Requires-Dist: curl-cffi ; extra == 'benchmark'
38
+ Requires-Dist: pycurl ; extra == 'benchmark'
39
+ Requires-Dist: typing-extensions ; extra == 'benchmark'
40
+ Requires-Dist: aiohttp ; extra == 'benchmark'
41
+ Requires-Dist: cbor2 ; extra == 'benchmark'
42
+ Requires-Dist: jupyter ; extra == 'benchmark'
43
+ Requires-Dist: ipykernel ; extra == 'benchmark'
44
+ Requires-Dist: gunicorn ; extra == 'benchmark'
45
+ Requires-Dist: fastapi ; extra == 'benchmark'
46
+ Provides-Extra: dev
47
+ Provides-Extra: docs
48
+ Provides-Extra: benchmark
49
+ License-File: LICENSE
50
+ Summary: Fast HTTP client for Python
51
+ Keywords: python,request
52
+ Author: thomasht86
53
+ License: MIT License
54
+ Requires-Python: >=3.10
55
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
56
+
57
+ # httpr
58
+
59
+ **Blazing fast http-client** for Python in Rust 🦀 that can be used as drop-in replacement for `httpx` and `requests` in most cases.
60
+
61
+ - **Fast**: `httpr` is built on top of `reqwests`, which is a blazing fast http client in Rust. Check out the [benchmark](#benchmark).
62
+ - **Both async and sync**: `httpr` provides both a sync and async client.
63
+ - **Lightweight**: `httpr` is a lightweight http client with zero python-dependencies.
64
+ - **Async**: first-class async support.
65
+ - **Streaming**: supports streaming responses for efficient memory usage with large payloads.
66
+ - **http2**: `httpr` supports HTTP/2.
67
+ - **mTLS**: `httpr` supports mTLS.
68
+
69
+ ## Not implemented yet
70
+
71
+ - **Fine-grained error handling**: Fine-grained error handling is not implemented yet.
72
+
73
+ ## Documentation
74
+
75
+ 📖 **Full documentation**: [thomasht86.github.io/httpr](https://thomasht86.github.io/httpr)
76
+
77
+ 🤖 **LLM-friendly docs**: [llms.txt](https://thomasht86.github.io/httpr/llms.txt) | [llms-full.txt](https://thomasht86.github.io/httpr/llms-full.txt)
78
+
79
+ ## Table of Contents
80
+
81
+ - [httpr](#httpr)
82
+ - [Not implemented yet](#not-implemented-yet)
83
+ - [Documentation](#documentation)
84
+ - [Table of Contents](#table-of-contents)
85
+ - [Installation](#installation)
86
+ - [Install with uv](#install-with-uv)
87
+ - [Install from PyPI](#install-from-pypi)
88
+ - [Benchmark](#benchmark)
89
+ - [Usage](#usage)
90
+ - [I. Client](#i-client)
91
+ - [Client methods](#client-methods)
92
+ - [Response object](#response-object)
93
+ - [Streaming responses](#streaming-responses)
94
+ - [Examples](#examples)
95
+ - [II. AsyncClient](#ii-asyncclient)
96
+ - [Precompiled wheels](#precompiled-wheels)
97
+ - [CI](#ci)
98
+ - [Acknowledgements](#acknowledgements)
99
+
100
+ ## Installation
101
+
102
+ ### Install with uv
103
+
104
+ ```python
105
+ uv add httpr
106
+ ```
107
+
108
+ or
109
+
110
+ ```python
111
+ uv pip install httpr
112
+ ```
113
+
114
+ ### Install from PyPI
115
+
116
+ ```python
117
+ pip install -U httpr
118
+ ```
119
+
120
+ ## Benchmark
121
+
122
+ ![](https://github.com/thomasht86/httpr/blob/main/benchmark.jpg?raw=true)
123
+
124
+ ## Usage
125
+
126
+ ### I. Client
127
+
128
+ ```python
129
+ class Client:
130
+ """Initializes an HTTP client.
131
+
132
+ Args:
133
+ auth (tuple[str, str| None] | None): Username and password for basic authentication. Default is None.
134
+ auth_bearer (str | None): Bearer token for authentication. Default is None.
135
+ params (dict[str, str] | None): Default query parameters to include in all requests. Default is None.
136
+ headers (dict[str, str] | None): Default headers to send with requests.
137
+ cookies (dict[str, str] | None): - Map of cookies to send with requests as the `Cookie` header.
138
+ timeout (float | None): HTTP request timeout in seconds. Default is 30.
139
+ cookie_store (bool | None): Enable a persistent cookie store. Received cookies will be preserved and included
140
+ in additional requests. Default is True.
141
+ referer (bool | None): Enable or disable automatic setting of the `Referer` header. Default is True.
142
+ proxy (str | None): Proxy URL for HTTP requests. Example: "socks5://127.0.0.1:9150". Default is None.
143
+ follow_redirects (bool | None): Whether to follow redirects. Default is True.
144
+ max_redirects (int | None): Maximum redirects to follow. Default 20. Applies if `follow_redirects` is True.
145
+ verify (bool | None): Verify SSL certificates. Default is True.
146
+ ca_cert_file (str | None): Path to CA certificate store. Default is None.
147
+ https_only` (bool | None): Restrict the Client to be used with HTTPS only requests. Default is `false`.
148
+ http2_only` (bool | None): If true - use only HTTP/2; if false - use only HTTP/1. Default is `false`.
149
+
150
+ """
151
+ ```
152
+
153
+ #### Client methods
154
+
155
+ The `Client` class provides a set of methods for making HTTP requests: `get`, `head`, `options`, `delete`, `post`, `put`, `patch`, each of which internally utilizes the `request()` method for execution. The parameters for these methods closely resemble those in `httpx`.
156
+ ```python
157
+ def get(
158
+ url: str,
159
+ params: dict[str, str] | None = None,
160
+ headers: dict[str, str] | None = None,
161
+ cookies: dict[str, str] | None = None,
162
+ auth: tuple[str, str| None] | None = None,
163
+ auth_bearer: str | None = None,
164
+ timeout: float | None = 30,
165
+ ):
166
+ """Performs a GET request to the specified URL.
167
+
168
+ Args:
169
+ url (str): The URL to which the request will be made.
170
+ params (dict[str, str] | None): A map of query parameters to append to the URL. Default is None.
171
+ headers (dict[str, str] | None): A map of HTTP headers to send with the request. Default is None.
172
+ cookies (dict[str, str] | None): - An optional map of cookies to send with requests as the `Cookie` header.
173
+ auth (tuple[str, str| None] | None): A tuple containing the username and an optional password
174
+ for basic authentication. Default is None.
175
+ auth_bearer (str | None): A string representing the bearer token for bearer token authentication. Default is None.
176
+ timeout (float | None): The timeout for the request in seconds. Default is 30.
177
+
178
+ """
179
+ ```
180
+ ```python
181
+ def post(
182
+ url: str,
183
+ params: dict[str, str] | None = None,
184
+ headers: dict[str, str] | None = None,
185
+ cookies: dict[str, str] | None = None,
186
+ content: bytes | None = None,
187
+ data: dict[str, Any] | None = None,
188
+ json: Any | None = None,
189
+ files: dict[str, str] | None = None,
190
+ auth: tuple[str, str| None] | None = None,
191
+ auth_bearer: str | None = None,
192
+ timeout: float | None = 30,
193
+ ):
194
+ """Performs a POST request to the specified URL.
195
+
196
+ Args:
197
+ url (str): The URL to which the request will be made.
198
+ params (dict[str, str] | None): A map of query parameters to append to the URL. Default is None.
199
+ headers (dict[str, str] | None): A map of HTTP headers to send with the request. Default is None.
200
+ cookies (dict[str, str] | None): - An optional map of cookies to send with requests as the `Cookie` header.
201
+ content (bytes | None): The content to send in the request body as bytes. Default is None.
202
+ data (dict[str, Any] | None): The form data to send in the request body. Default is None.
203
+ json (Any | None): A JSON serializable object to send in the request body. Default is None.
204
+ files (dict[str, str] | None): A map of file fields to file paths to be sent as multipart/form-data. Default is None.
205
+ auth (tuple[str, str| None] | None): A tuple containing the username and an optional password
206
+ for basic authentication. Default is None.
207
+ auth_bearer (str | None): A string representing the bearer token for bearer token authentication. Default is None.
208
+ timeout (float | None): The timeout for the request in seconds. Default is 30.
209
+
210
+ """
211
+ ```
212
+
213
+ #### Response object
214
+
215
+ The `Client` class returns a `Response` object that contains the following attributes and methods:
216
+
217
+ ```python
218
+ resp.content
219
+ resp.cookies
220
+ resp.encoding
221
+ resp.headers
222
+ resp.json()
223
+ resp.status_code
224
+ resp.text
225
+ resp.text_markdown # html is converted to markdown text using html2text-rs
226
+ resp.text_plain # html is converted to plain text
227
+ resp.text_rich # html is converted to rich text
228
+ resp.url
229
+ ```
230
+
231
+ #### Streaming responses
232
+
233
+ The `Client` class supports streaming responses for efficient memory usage when handling large payloads. Use the `stream()` context manager to iterate over response data without buffering the entire response in memory.
234
+
235
+ ```python
236
+ # Stream bytes chunks
237
+ with client.stream("GET", "https://example.com/large-file") as response:
238
+ print(f"Status: {response.status_code}")
239
+ for chunk in response.iter_bytes():
240
+ process(chunk)
241
+
242
+ # Stream text chunks
243
+ with client.stream("GET", "https://example.com/text") as response:
244
+ for text in response.iter_text():
245
+ print(text, end="")
246
+
247
+ # Stream line by line (useful for Server-Sent Events)
248
+ with client.stream("GET", "https://example.com/events") as response:
249
+ for line in response.iter_lines():
250
+ print(line.strip())
251
+
252
+ # Read entire response (if needed after checking headers)
253
+ with client.stream("GET", url) as response:
254
+ if response.status_code == 200:
255
+ content = response.read()
256
+ ```
257
+
258
+ **StreamingResponse attributes:**
259
+ - `status_code` - HTTP status code
260
+ - `headers` - Response headers (case-insensitive)
261
+ - `cookies` - Response cookies
262
+ - `url` - Final URL after redirects
263
+ - `is_closed` - Whether the stream has been closed
264
+ - `is_consumed` - Whether the stream has been fully consumed
265
+
266
+ **StreamingResponse methods:**
267
+ - `iter_bytes()` - Iterate over response as bytes chunks
268
+ - `iter_text()` - Iterate over response as text chunks (decoded using response encoding)
269
+ - `iter_lines()` - Iterate over response line by line
270
+ - `read()` - Read entire remaining response body into memory
271
+ - `close()` - Close the stream and release resources
272
+
273
+ **Important notes:**
274
+ - Streaming must be used as a context manager (with statement)
275
+ - Headers, cookies, and status code are available immediately before reading the body
276
+ - The response body is only read when you iterate over it or call `read()`
277
+ - Once consumed, the stream cannot be read again
278
+ - Streaming is supported for all HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
279
+
280
+ #### Examples
281
+
282
+ ```python
283
+ import httpr
284
+
285
+ # Initialize the client
286
+ client = httpr.Client()
287
+
288
+ # GET request
289
+ resp = client.get("https://tls.peet.ws/api/all")
290
+ print(resp.json())
291
+
292
+ # GET request with passing params and setting timeout
293
+ params = {"param1": "value1", "param2": "value2"}
294
+ resp = client.post(url="https://httpbin.org/anything", params=params, timeout=10)
295
+ print(r.text)
296
+
297
+ # POST Binary Request Data
298
+ content = b"some_data"
299
+ resp = client.post(url="https://httpbin.org/anything", content=content)
300
+ print(r.text)
301
+
302
+ # POST Form Encoded Data
303
+ data = {"key1": "value1", "key2": "value2"}
304
+ resp = client.post(url="https://httpbin.org/anything", data=data)
305
+ print(r.text)
306
+
307
+ # POST JSON Encoded Data
308
+ json = {"key1": "value1", "key2": "value2"}
309
+ resp = client.post(url="https://httpbin.org/anything", json=json)
310
+ print(r.text)
311
+
312
+ # POST Multipart-Encoded Files
313
+ files = {'file1': '/home/root/file1.txt', 'file2': 'home/root/file2.txt'}
314
+ r = client.post("https://httpbin.org/post", files=files)
315
+ print(r.text)
316
+
317
+ # Authentication using user/password
318
+ auth = ("user", "password")
319
+ resp = client.post(url="https://httpbin.org/anything", auth=auth)
320
+ print(r.text)
321
+
322
+ # Authentication using auth bearer
323
+ auth_bearer = "bearerXXXXXXXXXXXXXXXXXXXX"
324
+ resp = client.post(url="https://httpbin.org/anything", auth_bearer=auth_bearer)
325
+ print(r.text)
326
+
327
+ # Using proxy or env var HTTPR_PROXY
328
+ resp = httpr.Client(proxy="http://127.0.0.1:8080").get("https://tls.peet.ws/api/all")
329
+ print(resp.json())
330
+ export HTTPR_PROXY="socks5://127.0.0.1:1080"
331
+ resp = httpr.Client().get("https://tls.peet.ws/api/all")
332
+ print(resp.json())
333
+
334
+ # Using custom CA certificate store: env var HTTPR_CA_BUNDLE
335
+ resp = httpr.Client(ca_cert_file="/cert/cacert.pem").get("https://tls.peet.ws/api/all")
336
+ print(resp.json())
337
+ resp = httpr.Client(ca_cert_file=certifi.where()).get("https://tls.peet.ws/api/all")
338
+ print(resp.json())
339
+ export HTTPR_CA_BUNDLE="/home/user/Downloads/cert.pem"
340
+ resp = httpr.Client().get("https://tls.peet.ws/api/all")
341
+ print(resp.json())
342
+
343
+ # You can also use convenience functions that use a default Client instance under the hood:
344
+ # httpr.get() | httpr.head() | httpr.options() | httpr.delete() | httpr.post() | httpr.patch() | httpr.put()
345
+ resp = httpr.get("https://httpbin.org/anything")
346
+ print(r.text)
347
+ ```
348
+
349
+ ### II. AsyncClient
350
+
351
+ `httpr.AsyncClient()` is an asynchronous wrapper around the `httpr.Client` class, offering the same functions, behavior, and input arguments.
352
+
353
+ ```python
354
+ import asyncio
355
+ import logging
356
+
357
+ import httpr
358
+
359
+ async def aget_text(url):
360
+ async with httpr.AsyncClient() as client:
361
+ resp = await client.get(url)
362
+ return resp.text
363
+
364
+ async def main():
365
+ urls = ["https://nytimes.com/", "https://cnn.com/", "https://abcnews.go.com/"]
366
+ tasks = [aget_text(u) for u in urls]
367
+ results = await asyncio.gather(*tasks)
368
+
369
+ if __name__ == "__main__":
370
+ logging.basicConfig(level=logging.INFO)
371
+ asyncio.run(main())
372
+ ```
373
+
374
+ **Streaming with AsyncClient:**
375
+
376
+ The `AsyncClient` also supports streaming responses with the same API:
377
+
378
+ ```python
379
+ async with httpr.AsyncClient() as client:
380
+ async with client.stream("GET", "https://example.com/large-file") as response:
381
+ for chunk in response.iter_bytes():
382
+ process(chunk)
383
+ ```
384
+
385
+ Note: While the context manager is async, the iteration over chunks (`iter_bytes()`, `iter_text()`, `iter_lines()`) is synchronous.
386
+
387
+ ## Precompiled wheels
388
+
389
+ Provides precompiled wheels for the following platforms:
390
+
391
+ - 🐧 linux: `amd64`, `aarch64`, `armv7` (aarch64 and armv7 builds are `manylinux_2_34` compatible. `ubuntu>=22.04`, `debian>=12`)
392
+ - 🐧 musllinux: `amd64`, `aarch64`
393
+ - 🪟 windows: `amd64`
394
+ - 🍏 macos: `amd64`, `aarch64`.
395
+
396
+ ## CI
397
+
398
+ | Job | PRs | Push to main | Tags (Release) | Manual |
399
+ |-----|:---:|:------------:|:--------------:|:------:|
400
+ | `lint` | ✓ | | | |
401
+ | `test` (Python 3.10-3.14) | ✓ | ✓ | ✓ | |
402
+ | `docs` (build) | ✓ | | | |
403
+ | `linux`, `musllinux`, `windows`, `macos`, `sdist` | | | ✓ | ✓ |
404
+ | `release` (PyPI publish) | | | ✓ | ✓ |
405
+ | `benchmark` | | | ✓ | ✓ |
406
+
407
+ - **PRs**: Run lint, tests across Python 3.10-3.14 matrix, and verify docs build
408
+ - **Push to main**: Run tests only
409
+ - **Tags**: Run tests, build wheels, publish stable release to PyPI, run benchmarks
410
+ - **Manual**: Full multi-platform wheel builds with release and benchmarks
411
+
412
+ ## Acknowledgements
413
+
414
+ - [uv](https://docs.astral.sh/uv/): The package manager used, and for leading the way in the "Rust for python tools"-sphere.
415
+ - [primp](https://github.com/deedy5/primp): *A lot* of code is borrowed from primp, that wraps rust library `rquest` for python in a similar way. If primp supported mTLS, I would have used it instead.
416
+ - [reqwests](https://github.com/seanmonstar/reqwest): The rust library that powers httpr.
417
+ - [pyo3](https://github.com/PyO3/pyo3)
418
+ - [maturin](https://github.com/PyO3/maturin)
@@ -0,0 +1,8 @@
1
+ httpr-0.2.6.dist-info/METADATA,sha256=pLYu_b1sIi9EB9OQxyVtpPk0vAEk4exkEGtOVGpWKJQ,16738
2
+ httpr-0.2.6.dist-info/WHEEL,sha256=mgJTbGuFgJJEI1eZRs-zAv9SW06M0ztq8kWUPtBdU7Q,94
3
+ httpr-0.2.6.dist-info/licenses/LICENSE,sha256=O15TIxUAXq6sSpPu0K3CJu_dT5ZzCgIk7hQtZsf0lEk,1084
4
+ httpr/__init__.py,sha256=9fWQvAMuKrwaLrcN3GuJUvU8MlLX9lGEvGmBKG0o9DY,31209
5
+ httpr/httpr.cp313t-win32.pyd,sha256=roCunKSdgY2OMc7ivdKqBbN6c3BwaF2F4_Rrq9oBr44,4087296
6
+ httpr/httpr.pyi,sha256=yGciDXixFhcw9RjtIZVYX8DIuc3TRlSRfVwafTZLi_E,23306
7
+ httpr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ httpr-0.2.6.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313t-win32
@@ -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.