httpr 0.4.8__tar.gz → 0.5.2__tar.gz
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-0.4.8 → httpr-0.5.2}/.github/workflows/CI.yml +8 -69
- {httpr-0.4.8 → httpr-0.5.2}/.github/workflows/mkdocs.yml +0 -9
- {httpr-0.4.8 → httpr-0.5.2}/CLAUDE.md +2 -1
- {httpr-0.4.8 → httpr-0.5.2}/Cargo.lock +76 -93
- {httpr-0.4.8 → httpr-0.5.2}/Cargo.toml +4 -4
- {httpr-0.4.8 → httpr-0.5.2}/PKG-INFO +24 -6
- {httpr-0.4.8 → httpr-0.5.2}/README.md +23 -5
- {httpr-0.4.8 → httpr-0.5.2}/docs/api/index.md +4 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/api/response.md +101 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/tutorial/making-requests.md +12 -3
- {httpr-0.4.8 → httpr-0.5.2}/docs/tutorial/response-handling.md +47 -11
- {httpr-0.4.8 → httpr-0.5.2}/httpr/__init__.py +56 -2
- {httpr-0.4.8 → httpr-0.5.2}/httpr/httpr.pyi +85 -1
- {httpr-0.4.8 → httpr-0.5.2}/pyproject.toml +1 -1
- {httpr-0.4.8 → httpr-0.5.2}/src/exceptions.rs +1 -1
- {httpr-0.4.8 → httpr-0.5.2}/src/lib.rs +23 -0
- {httpr-0.4.8 → httpr-0.5.2}/src/response.rs +150 -2
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_client.py +45 -0
- httpr-0.5.2/tests/unit/test_response.py +69 -0
- {httpr-0.4.8 → httpr-0.5.2}/uv.lock +139 -144
- httpr-0.4.8/benchmark/generate_image.py +0 -149
- {httpr-0.4.8 → httpr-0.5.2}/.github/actions/set-version/action.yml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.github/copilot-instructions.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.github/workflows/CI.yml.backup +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.github/workflows/benchmark.yml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.github/workflows/copilot-setup-steps.yml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.github/workflows/set_version.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.gitignore +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/.pre-commit-config.yaml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/LICENSE +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/Taskfile.yaml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark/README.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark/__init__.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark/benchmark.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark/benchmark_cbor.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark/server.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/benchmark.jpg +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/advanced/cookies.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/advanced/index.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/advanced/proxy.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/advanced/ssl-tls.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/api/async-client.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/api/client.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/api/functions.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/index.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/quickstart.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/tutorial/async.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/tutorial/authentication.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/tutorial/index.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/writings/index.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/docs/writings/posts/2025-02-24-python-http-clients-suck.md +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/httpr/py.typed +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/httpr.code-workspace +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/mkdocs.yml +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/scripts/generate_certs.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/src/traits.rs +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/src/utils.rs +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/benchmark/__init__.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/benchmark/test_performance.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/conftest.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/__init__.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_async.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_auth.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_redirects.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_ssl.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_streaming.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/e2e/test_uploads.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/__init__.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/cbor_test_server.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/httpx_conns.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_asyncclient.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_cbor.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_defs.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_docs.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_exceptions.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_ssl.py +0 -0
- {httpr-0.4.8 → httpr-0.5.2}/tests/unit/test_streaming.py +0 -0
|
@@ -4,8 +4,6 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
-
paths-ignore:
|
|
8
|
-
- "*.jpg" # Prevents the benchmark image update from triggering CI
|
|
9
7
|
tags:
|
|
10
8
|
- "*"
|
|
11
9
|
pull_request:
|
|
@@ -176,7 +174,7 @@ jobs:
|
|
|
176
174
|
uses: PyO3/maturin-action@v1
|
|
177
175
|
with:
|
|
178
176
|
target: ${{ matrix.platform.target }}
|
|
179
|
-
args: --release --out dist -i python3.
|
|
177
|
+
args: --release --out dist -i python3.14t
|
|
180
178
|
sccache: true
|
|
181
179
|
manylinux: auto
|
|
182
180
|
- name: Upload wheels
|
|
@@ -231,7 +229,7 @@ jobs:
|
|
|
231
229
|
uses: PyO3/maturin-action@v1
|
|
232
230
|
with:
|
|
233
231
|
target: ${{ matrix.platform.target }}
|
|
234
|
-
args: --release --out dist -i python3.
|
|
232
|
+
args: --release --out dist -i python3.14t
|
|
235
233
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
236
234
|
manylinux: musllinux_1_2
|
|
237
235
|
- name: Upload wheels
|
|
@@ -287,7 +285,7 @@ jobs:
|
|
|
287
285
|
uses: PyO3/maturin-action@v1
|
|
288
286
|
with:
|
|
289
287
|
target: ${{ matrix.platform.target }}
|
|
290
|
-
args: --release --out dist -i python3.
|
|
288
|
+
args: --release --out dist -i python3.14t
|
|
291
289
|
sccache: true
|
|
292
290
|
- name: Upload wheels
|
|
293
291
|
uses: actions/upload-artifact@v4
|
|
@@ -295,6 +293,10 @@ jobs:
|
|
|
295
293
|
name: wheels-windows-${{ matrix.platform.target }}
|
|
296
294
|
path: dist
|
|
297
295
|
- name: pytest
|
|
296
|
+
# Skip pytest on x86 - cryptography (pulled in via the trustme dev
|
|
297
|
+
# dependency) no longer ships 32-bit Windows wheels and fails to build
|
|
298
|
+
# from source. The x64 job provides test coverage for Windows.
|
|
299
|
+
if: ${{ matrix.platform.target == 'x64' }}
|
|
298
300
|
shell: bash
|
|
299
301
|
env:
|
|
300
302
|
RUSTC_WRAPPER: ""
|
|
@@ -333,7 +335,7 @@ jobs:
|
|
|
333
335
|
uses: PyO3/maturin-action@v1
|
|
334
336
|
with:
|
|
335
337
|
target: ${{ matrix.platform.target }}
|
|
336
|
-
args: --release --out dist -i python3.
|
|
338
|
+
args: --release --out dist -i python3.14t
|
|
337
339
|
sccache: true
|
|
338
340
|
- name: Upload wheels
|
|
339
341
|
uses: actions/upload-artifact@v4
|
|
@@ -401,66 +403,3 @@ jobs:
|
|
|
401
403
|
with:
|
|
402
404
|
command: upload
|
|
403
405
|
args: --non-interactive --skip-existing wheels-*/*
|
|
404
|
-
|
|
405
|
-
benchmark:
|
|
406
|
-
permissions:
|
|
407
|
-
contents: write
|
|
408
|
-
runs-on: ubuntu-latest
|
|
409
|
-
needs: [linux]
|
|
410
|
-
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
|
|
411
|
-
steps:
|
|
412
|
-
- uses: actions/checkout@v4
|
|
413
|
-
with:
|
|
414
|
-
fetch-depth: 0
|
|
415
|
-
- uses: astral-sh/setup-uv@v7
|
|
416
|
-
with:
|
|
417
|
-
python-version: "3.12"
|
|
418
|
-
- name: Download wheels
|
|
419
|
-
uses: actions/download-artifact@v4
|
|
420
|
-
with:
|
|
421
|
-
name: wheels-linux-x86_64
|
|
422
|
-
- name: Start Uvicorn server
|
|
423
|
-
env:
|
|
424
|
-
BENCHMARK_HOST: 0.0.0.0
|
|
425
|
-
BENCHMARK_PORT: "8000"
|
|
426
|
-
run: |
|
|
427
|
-
uv run --script benchmark/server.py &
|
|
428
|
-
sleep 10
|
|
429
|
-
- name: Run benchmark
|
|
430
|
-
run: |
|
|
431
|
-
# Extract version from tag (v0.3.0 -> 0.3.0) or use 'dev' for manual runs
|
|
432
|
-
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
|
433
|
-
HTTPR_VERSION=${GITHUB_REF#refs/tags/v}
|
|
434
|
-
else
|
|
435
|
-
HTTPR_VERSION="dev"
|
|
436
|
-
fi
|
|
437
|
-
# The script declares `httpr` in its PEP 723 deps; --find-links lets uv
|
|
438
|
-
# pick the freshly-built wheel from the workspace instead of PyPI.
|
|
439
|
-
uv run \
|
|
440
|
-
--find-links ./ \
|
|
441
|
-
--refresh-package httpr \
|
|
442
|
-
--script benchmark/benchmark.py --httpr-version "$HTTPR_VERSION"
|
|
443
|
-
- name: Generate and deploy benchmark image to gh-pages
|
|
444
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
445
|
-
run: |
|
|
446
|
-
uv run --script benchmark/generate_image.py
|
|
447
|
-
git config --global user.name 'github-actions[bot]'
|
|
448
|
-
git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
|
449
|
-
|
|
450
|
-
# Save the generated image
|
|
451
|
-
cp benchmark.jpg /tmp/benchmark.jpg
|
|
452
|
-
|
|
453
|
-
# Fetch and checkout gh-pages
|
|
454
|
-
git fetch origin gh-pages:gh-pages
|
|
455
|
-
git checkout gh-pages
|
|
456
|
-
|
|
457
|
-
# Copy the benchmark image
|
|
458
|
-
cp /tmp/benchmark.jpg benchmark.jpg
|
|
459
|
-
|
|
460
|
-
git add benchmark.jpg
|
|
461
|
-
if ! git diff --quiet --cached; then
|
|
462
|
-
git commit -m "Update benchmark image for ${{ github.ref_name }}"
|
|
463
|
-
git push origin gh-pages
|
|
464
|
-
else
|
|
465
|
-
echo "No changes to commit"
|
|
466
|
-
fi
|
|
@@ -50,10 +50,6 @@ jobs:
|
|
|
50
50
|
if git show gh-pages:dev/bench/index.html > /tmp/bench-backup/index.html 2>/dev/null; then
|
|
51
51
|
echo "Found existing benchmark index.html, will preserve it"
|
|
52
52
|
fi
|
|
53
|
-
# Save benchmark image if it exists
|
|
54
|
-
if git show gh-pages:benchmark.jpg > /tmp/bench-backup/benchmark.jpg 2>/dev/null; then
|
|
55
|
-
echo "Found existing benchmark.jpg, will preserve it"
|
|
56
|
-
fi
|
|
57
53
|
|
|
58
54
|
# Switch to gh-pages branch
|
|
59
55
|
git checkout gh-pages || git checkout --orphan gh-pages
|
|
@@ -75,11 +71,6 @@ jobs:
|
|
|
75
71
|
[ -f /tmp/bench-backup/index.html ] && cp /tmp/bench-backup/index.html dev/bench/
|
|
76
72
|
echo "Restored benchmark chart files"
|
|
77
73
|
fi
|
|
78
|
-
# Restore benchmark image if it existed
|
|
79
|
-
if [ -f /tmp/bench-backup/benchmark.jpg ]; then
|
|
80
|
-
cp /tmp/bench-backup/benchmark.jpg benchmark.jpg
|
|
81
|
-
echo "Restored benchmark.jpg"
|
|
82
|
-
fi
|
|
83
74
|
|
|
84
75
|
# Add all files and commit
|
|
85
76
|
git add -A
|
|
@@ -151,7 +151,8 @@ uv run python benchmark.py # Terminal 2: Run benchmarks
|
|
|
151
151
|
|
|
152
152
|
### Headers Behavior
|
|
153
153
|
- Headers are lowercased internally (HTTP/2 spec)
|
|
154
|
-
- `client.headers` getter
|
|
154
|
+
- `client.headers` getter returns a live `_ClientHeaders` view; in-place mutations (`__setitem__`, `del`, `update`, `pop`, `popitem`, `setdefault`, `clear`) mirror to the client via Rust `set_header`/`del_header`
|
|
155
|
+
- `client.headers` getter excludes `Cookie` header; `set_headers` preserves the existing `Cookie` header so header mutation never clobbers cookies
|
|
155
156
|
- `client.cookies` getter/setter extracts from `Cookie` header
|
|
156
157
|
|
|
157
158
|
### Request Body
|
|
@@ -25,9 +25,9 @@ dependencies = [
|
|
|
25
25
|
|
|
26
26
|
[[package]]
|
|
27
27
|
name = "anyhow"
|
|
28
|
-
version = "1.0.
|
|
28
|
+
version = "1.0.103"
|
|
29
29
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
-
checksum = "
|
|
30
|
+
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
|
31
31
|
|
|
32
32
|
[[package]]
|
|
33
33
|
name = "arc-swap"
|
|
@@ -56,12 +56,6 @@ version = "1.1.2"
|
|
|
56
56
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
57
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
|
58
58
|
|
|
59
|
-
[[package]]
|
|
60
|
-
name = "autocfg"
|
|
61
|
-
version = "1.5.0"
|
|
62
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
-
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
64
|
-
|
|
65
59
|
[[package]]
|
|
66
60
|
name = "base64"
|
|
67
61
|
version = "0.22.1"
|
|
@@ -131,6 +125,17 @@ version = "0.2.1"
|
|
|
131
125
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
132
126
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
|
133
127
|
|
|
128
|
+
[[package]]
|
|
129
|
+
name = "chacha20"
|
|
130
|
+
version = "0.10.1"
|
|
131
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
132
|
+
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
|
133
|
+
dependencies = [
|
|
134
|
+
"cfg-if",
|
|
135
|
+
"cpufeatures",
|
|
136
|
+
"rand_core 0.10.1",
|
|
137
|
+
]
|
|
138
|
+
|
|
134
139
|
[[package]]
|
|
135
140
|
name = "compression-codecs"
|
|
136
141
|
version = "0.4.38"
|
|
@@ -180,6 +185,15 @@ dependencies = [
|
|
|
180
185
|
"url",
|
|
181
186
|
]
|
|
182
187
|
|
|
188
|
+
[[package]]
|
|
189
|
+
name = "cpufeatures"
|
|
190
|
+
version = "0.3.0"
|
|
191
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
192
|
+
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
|
193
|
+
dependencies = [
|
|
194
|
+
"libc",
|
|
195
|
+
]
|
|
196
|
+
|
|
183
197
|
[[package]]
|
|
184
198
|
name = "crc32fast"
|
|
185
199
|
version = "1.5.0"
|
|
@@ -376,10 +390,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
376
390
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
|
377
391
|
dependencies = [
|
|
378
392
|
"cfg-if",
|
|
379
|
-
"js-sys",
|
|
380
393
|
"libc",
|
|
381
|
-
"r-efi",
|
|
394
|
+
"r-efi 5.3.0",
|
|
382
395
|
"wasip2",
|
|
396
|
+
]
|
|
397
|
+
|
|
398
|
+
[[package]]
|
|
399
|
+
name = "getrandom"
|
|
400
|
+
version = "0.4.3"
|
|
401
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
402
|
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
403
|
+
dependencies = [
|
|
404
|
+
"cfg-if",
|
|
405
|
+
"js-sys",
|
|
406
|
+
"libc",
|
|
407
|
+
"r-efi 6.0.0",
|
|
408
|
+
"rand_core 0.10.1",
|
|
383
409
|
"wasm-bindgen",
|
|
384
410
|
]
|
|
385
411
|
|
|
@@ -492,7 +518,7 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
|
|
492
518
|
|
|
493
519
|
[[package]]
|
|
494
520
|
name = "httpr"
|
|
495
|
-
version = "0.
|
|
521
|
+
version = "0.5.2"
|
|
496
522
|
dependencies = [
|
|
497
523
|
"anyhow",
|
|
498
524
|
"bytes",
|
|
@@ -688,15 +714,6 @@ dependencies = [
|
|
|
688
714
|
"serde_core",
|
|
689
715
|
]
|
|
690
716
|
|
|
691
|
-
[[package]]
|
|
692
|
-
name = "indoc"
|
|
693
|
-
version = "2.0.7"
|
|
694
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
695
|
-
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
696
|
-
dependencies = [
|
|
697
|
-
"rustversion",
|
|
698
|
-
]
|
|
699
|
-
|
|
700
717
|
[[package]]
|
|
701
718
|
name = "ipnet"
|
|
702
719
|
version = "2.12.0"
|
|
@@ -807,15 +824,6 @@ version = "2.8.0"
|
|
|
807
824
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
808
825
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
809
826
|
|
|
810
|
-
[[package]]
|
|
811
|
-
name = "memoffset"
|
|
812
|
-
version = "0.9.1"
|
|
813
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
814
|
-
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
815
|
-
dependencies = [
|
|
816
|
-
"autocfg",
|
|
817
|
-
]
|
|
818
|
-
|
|
819
827
|
[[package]]
|
|
820
828
|
name = "mime"
|
|
821
829
|
version = "0.3.17"
|
|
@@ -987,15 +995,6 @@ version = "0.2.0"
|
|
|
987
995
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
988
996
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
|
989
997
|
|
|
990
|
-
[[package]]
|
|
991
|
-
name = "ppv-lite86"
|
|
992
|
-
version = "0.2.21"
|
|
993
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
994
|
-
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
|
995
|
-
dependencies = [
|
|
996
|
-
"zerocopy",
|
|
997
|
-
]
|
|
998
|
-
|
|
999
998
|
[[package]]
|
|
1000
999
|
name = "precomputed-hash"
|
|
1001
1000
|
version = "0.1.1"
|
|
@@ -1029,38 +1028,34 @@ dependencies = [
|
|
|
1029
1028
|
|
|
1030
1029
|
[[package]]
|
|
1031
1030
|
name = "pyo3"
|
|
1032
|
-
version = "0.
|
|
1031
|
+
version = "0.29.0"
|
|
1033
1032
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1034
|
-
checksum = "
|
|
1033
|
+
checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
|
|
1035
1034
|
dependencies = [
|
|
1036
1035
|
"anyhow",
|
|
1037
1036
|
"indexmap",
|
|
1038
|
-
"indoc",
|
|
1039
1037
|
"libc",
|
|
1040
|
-
"memoffset",
|
|
1041
1038
|
"once_cell",
|
|
1042
1039
|
"portable-atomic",
|
|
1043
1040
|
"pyo3-build-config",
|
|
1044
1041
|
"pyo3-ffi",
|
|
1045
1042
|
"pyo3-macros",
|
|
1046
|
-
"unindent",
|
|
1047
1043
|
]
|
|
1048
1044
|
|
|
1049
1045
|
[[package]]
|
|
1050
1046
|
name = "pyo3-build-config"
|
|
1051
|
-
version = "0.
|
|
1047
|
+
version = "0.29.0"
|
|
1052
1048
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1053
|
-
checksum = "
|
|
1049
|
+
checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
|
|
1054
1050
|
dependencies = [
|
|
1055
|
-
"python3-dll-a",
|
|
1056
1051
|
"target-lexicon",
|
|
1057
1052
|
]
|
|
1058
1053
|
|
|
1059
1054
|
[[package]]
|
|
1060
1055
|
name = "pyo3-ffi"
|
|
1061
|
-
version = "0.
|
|
1056
|
+
version = "0.29.0"
|
|
1062
1057
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1063
|
-
checksum = "
|
|
1058
|
+
checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
|
|
1064
1059
|
dependencies = [
|
|
1065
1060
|
"libc",
|
|
1066
1061
|
"pyo3-build-config",
|
|
@@ -1068,9 +1063,9 @@ dependencies = [
|
|
|
1068
1063
|
|
|
1069
1064
|
[[package]]
|
|
1070
1065
|
name = "pyo3-log"
|
|
1071
|
-
version = "0.13.
|
|
1066
|
+
version = "0.13.4"
|
|
1072
1067
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1073
|
-
checksum = "
|
|
1068
|
+
checksum = "f64083bd3a16a353d9d62335808e8e13d0552d2a2b83fdb084496192dcfa9fcd"
|
|
1074
1069
|
dependencies = [
|
|
1075
1070
|
"arc-swap",
|
|
1076
1071
|
"log",
|
|
@@ -1079,9 +1074,9 @@ dependencies = [
|
|
|
1079
1074
|
|
|
1080
1075
|
[[package]]
|
|
1081
1076
|
name = "pyo3-macros"
|
|
1082
|
-
version = "0.
|
|
1077
|
+
version = "0.29.0"
|
|
1083
1078
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1084
|
-
checksum = "
|
|
1079
|
+
checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
|
|
1085
1080
|
dependencies = [
|
|
1086
1081
|
"proc-macro2",
|
|
1087
1082
|
"pyo3-macros-backend",
|
|
@@ -1091,31 +1086,21 @@ dependencies = [
|
|
|
1091
1086
|
|
|
1092
1087
|
[[package]]
|
|
1093
1088
|
name = "pyo3-macros-backend"
|
|
1094
|
-
version = "0.
|
|
1089
|
+
version = "0.29.0"
|
|
1095
1090
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1096
|
-
checksum = "
|
|
1091
|
+
checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
|
|
1097
1092
|
dependencies = [
|
|
1098
1093
|
"heck",
|
|
1099
1094
|
"proc-macro2",
|
|
1100
|
-
"pyo3-build-config",
|
|
1101
1095
|
"quote",
|
|
1102
1096
|
"syn",
|
|
1103
1097
|
]
|
|
1104
1098
|
|
|
1105
|
-
[[package]]
|
|
1106
|
-
name = "python3-dll-a"
|
|
1107
|
-
version = "0.2.15"
|
|
1108
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1109
|
-
checksum = "d80ba7540edb18890d444c5aa8e1f1f99b1bdf26fb26ae383135325f4a36042b"
|
|
1110
|
-
dependencies = [
|
|
1111
|
-
"cc",
|
|
1112
|
-
]
|
|
1113
|
-
|
|
1114
1099
|
[[package]]
|
|
1115
1100
|
name = "pythonize"
|
|
1116
|
-
version = "0.
|
|
1101
|
+
version = "0.29.0"
|
|
1117
1102
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1118
|
-
checksum = "
|
|
1103
|
+
checksum = "6ec376e1216e0c929a74964ce2020012a1a39f32d80e78aa688721219ea7fb89"
|
|
1119
1104
|
dependencies = [
|
|
1120
1105
|
"pyo3",
|
|
1121
1106
|
"serde",
|
|
@@ -1143,14 +1128,15 @@ dependencies = [
|
|
|
1143
1128
|
|
|
1144
1129
|
[[package]]
|
|
1145
1130
|
name = "quinn-proto"
|
|
1146
|
-
version = "0.11.
|
|
1131
|
+
version = "0.11.16"
|
|
1147
1132
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1148
|
-
checksum = "
|
|
1133
|
+
checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
|
|
1149
1134
|
dependencies = [
|
|
1150
1135
|
"bytes",
|
|
1151
|
-
"getrandom 0.3
|
|
1136
|
+
"getrandom 0.4.3",
|
|
1152
1137
|
"lru-slab",
|
|
1153
|
-
"rand 0.
|
|
1138
|
+
"rand 0.10.2",
|
|
1139
|
+
"rand_pcg",
|
|
1154
1140
|
"ring",
|
|
1155
1141
|
"rustc-hash",
|
|
1156
1142
|
"rustls",
|
|
@@ -1191,6 +1177,12 @@ version = "5.3.0"
|
|
|
1191
1177
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1192
1178
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|
1193
1179
|
|
|
1180
|
+
[[package]]
|
|
1181
|
+
name = "r-efi"
|
|
1182
|
+
version = "6.0.0"
|
|
1183
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1184
|
+
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|
1185
|
+
|
|
1194
1186
|
[[package]]
|
|
1195
1187
|
name = "rand"
|
|
1196
1188
|
version = "0.8.6"
|
|
@@ -1202,22 +1194,13 @@ dependencies = [
|
|
|
1202
1194
|
|
|
1203
1195
|
[[package]]
|
|
1204
1196
|
name = "rand"
|
|
1205
|
-
version = "0.
|
|
1206
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1207
|
-
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
|
|
1208
|
-
dependencies = [
|
|
1209
|
-
"rand_chacha",
|
|
1210
|
-
"rand_core 0.9.5",
|
|
1211
|
-
]
|
|
1212
|
-
|
|
1213
|
-
[[package]]
|
|
1214
|
-
name = "rand_chacha"
|
|
1215
|
-
version = "0.9.0"
|
|
1197
|
+
version = "0.10.2"
|
|
1216
1198
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1217
|
-
checksum = "
|
|
1199
|
+
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
|
1218
1200
|
dependencies = [
|
|
1219
|
-
"
|
|
1220
|
-
"
|
|
1201
|
+
"chacha20",
|
|
1202
|
+
"getrandom 0.4.3",
|
|
1203
|
+
"rand_core 0.10.1",
|
|
1221
1204
|
]
|
|
1222
1205
|
|
|
1223
1206
|
[[package]]
|
|
@@ -1228,11 +1211,17 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
|
1228
1211
|
|
|
1229
1212
|
[[package]]
|
|
1230
1213
|
name = "rand_core"
|
|
1231
|
-
version = "0.
|
|
1214
|
+
version = "0.10.1"
|
|
1232
1215
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1233
|
-
checksum = "
|
|
1216
|
+
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
|
1217
|
+
|
|
1218
|
+
[[package]]
|
|
1219
|
+
name = "rand_pcg"
|
|
1220
|
+
version = "0.10.2"
|
|
1221
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1222
|
+
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
|
|
1234
1223
|
dependencies = [
|
|
1235
|
-
"
|
|
1224
|
+
"rand_core 0.10.1",
|
|
1236
1225
|
]
|
|
1237
1226
|
|
|
1238
1227
|
[[package]]
|
|
@@ -1803,12 +1792,6 @@ version = "0.2.2"
|
|
|
1803
1792
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1804
1793
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
|
1805
1794
|
|
|
1806
|
-
[[package]]
|
|
1807
|
-
name = "unindent"
|
|
1808
|
-
version = "0.2.4"
|
|
1809
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1810
|
-
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
1811
|
-
|
|
1812
1795
|
[[package]]
|
|
1813
1796
|
name = "untrusted"
|
|
1814
1797
|
version = "0.9.0"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "httpr"
|
|
3
3
|
# Version is set dynamically by CI from git tags (e.g., v1.2.3 -> 1.2.3).
|
|
4
4
|
# Do not edit manually. See .github/actions/set-version/ for details.
|
|
5
|
-
version = "0.
|
|
5
|
+
version = "0.5.2"
|
|
6
6
|
edition = "2021"
|
|
7
7
|
description = "Fast HTTP client for python"
|
|
8
8
|
authors = ["thomasht86"]
|
|
@@ -15,7 +15,7 @@ name = "httpr"
|
|
|
15
15
|
crate-type = ["cdylib"]
|
|
16
16
|
|
|
17
17
|
[dependencies]
|
|
18
|
-
pyo3 = { version = "0.
|
|
18
|
+
pyo3 = { version = "0.29.0", features = [
|
|
19
19
|
"extension-module",
|
|
20
20
|
"abi3-py39",
|
|
21
21
|
"indexmap",
|
|
@@ -24,7 +24,7 @@ pyo3 = { version = "0.27.0", features = [
|
|
|
24
24
|
] }
|
|
25
25
|
anyhow = "1.0.95"
|
|
26
26
|
tracing = { version = "0.1.41", features = ["log-always"] }
|
|
27
|
-
pyo3-log = "0.13.
|
|
27
|
+
pyo3-log = "0.13.4"
|
|
28
28
|
reqwest = { version = "0.12", default-features = false, features = [
|
|
29
29
|
"cookies",
|
|
30
30
|
"json",
|
|
@@ -44,7 +44,7 @@ tokio = { version = "1.43.0", features = ["full"] }
|
|
|
44
44
|
tokio-util = { version = "0.7.13", features = ["codec"] } # for multipart
|
|
45
45
|
html2text = "0.13.6"
|
|
46
46
|
bytes = "1.10.0"
|
|
47
|
-
pythonize = "0.
|
|
47
|
+
pythonize = "0.29.0"
|
|
48
48
|
serde_json = "1.0.138"
|
|
49
49
|
serde_cbor_2 = "0.13"
|
|
50
50
|
webpki-root-certs = "0.26.8"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: httpr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -107,7 +107,11 @@ pip install -U httpr
|
|
|
107
107
|
|
|
108
108
|
## Benchmark
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
Performance is tracked continuously with [github-action-benchmark](https://github.com/benchmark-action/github-action-benchmark): on every push to `main`, the benchmark suite (`tests/benchmark/`) runs in CI and the results are published as interactive charts.
|
|
111
|
+
|
|
112
|
+
**📈 [View live benchmark results](https://thomasht86.github.io/httpr/dev/bench/)**
|
|
113
|
+
|
|
114
|
+
To run the benchmarks locally, see [benchmark/README.md](benchmark/README.md).
|
|
111
115
|
|
|
112
116
|
## Usage
|
|
113
117
|
|
|
@@ -209,6 +213,15 @@ resp.encoding
|
|
|
209
213
|
resp.headers
|
|
210
214
|
resp.json()
|
|
211
215
|
resp.status_code
|
|
216
|
+
resp.reason_phrase # e.g. "OK", "Not Found"
|
|
217
|
+
resp.raise_for_status() # raise HTTPStatusError on non-2xx (returns self)
|
|
218
|
+
resp.is_informational # 1xx
|
|
219
|
+
resp.is_success # 2xx
|
|
220
|
+
resp.is_redirect # 3xx
|
|
221
|
+
resp.is_client_error # 4xx
|
|
222
|
+
resp.is_server_error # 5xx
|
|
223
|
+
resp.is_error # 4xx or 5xx
|
|
224
|
+
resp.has_redirect_location # 3xx with a Location header
|
|
212
225
|
resp.text
|
|
213
226
|
resp.text_markdown # html is converted to markdown text using html2text-rs
|
|
214
227
|
resp.text_plain # html is converted to plain text
|
|
@@ -216,6 +229,9 @@ resp.text_rich # html is converted to rich text
|
|
|
216
229
|
resp.url
|
|
217
230
|
```
|
|
218
231
|
|
|
232
|
+
`raise_for_status()` follows `httpx` semantics: any non-2xx status raises
|
|
233
|
+
`HTTPStatusError` (not just 4xx/5xx as in `requests`).
|
|
234
|
+
|
|
219
235
|
#### Streaming responses
|
|
220
236
|
|
|
221
237
|
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.
|
|
@@ -245,6 +261,9 @@ with client.stream("GET", url) as response:
|
|
|
245
261
|
|
|
246
262
|
**StreamingResponse attributes:**
|
|
247
263
|
- `status_code` - HTTP status code
|
|
264
|
+
- `reason_phrase` - Canonical reason phrase (e.g. "OK")
|
|
265
|
+
- `raise_for_status()` - Raise `HTTPStatusError` on a non-2xx status (returns self)
|
|
266
|
+
- `is_success` / `is_error` / `is_redirect` / ... - Status-class helpers (same as `Response`)
|
|
248
267
|
- `headers` - Response headers (case-insensitive)
|
|
249
268
|
- `cookies` - Response cookies
|
|
250
269
|
- `url` - Final URL after redirects
|
|
@@ -449,12 +468,11 @@ task httpbun:logs # Show container logs
|
|
|
449
468
|
| `docs` (build) | ✓ | | | |
|
|
450
469
|
| `linux`, `musllinux`, `windows`, `macos`, `sdist` | | | ✓ | ✓ |
|
|
451
470
|
| `release` (PyPI publish) | | | ✓ | ✓ |
|
|
452
|
-
| `benchmark` | | | ✓ | ✓ |
|
|
453
471
|
|
|
454
472
|
- **PRs**: Run lint, tests across Python 3.10-3.14 matrix, and verify docs build
|
|
455
|
-
- **Push to main**: Run tests
|
|
456
|
-
- **Tags**: Run tests, build wheels, publish stable release to PyPI
|
|
457
|
-
- **Manual**: Full multi-platform wheel builds with release
|
|
473
|
+
- **Push to main**: Run tests, then the separate `Benchmark` workflow runs the benchmark suite and publishes results to the [live benchmark charts](https://thomasht86.github.io/httpr/dev/bench/)
|
|
474
|
+
- **Tags**: Run tests, build wheels, publish stable release to PyPI
|
|
475
|
+
- **Manual**: Full multi-platform wheel builds with release
|
|
458
476
|
|
|
459
477
|
## Acknowledgements
|
|
460
478
|
|
|
@@ -63,7 +63,11 @@ pip install -U httpr
|
|
|
63
63
|
|
|
64
64
|
## Benchmark
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Performance is tracked continuously with [github-action-benchmark](https://github.com/benchmark-action/github-action-benchmark): on every push to `main`, the benchmark suite (`tests/benchmark/`) runs in CI and the results are published as interactive charts.
|
|
67
|
+
|
|
68
|
+
**📈 [View live benchmark results](https://thomasht86.github.io/httpr/dev/bench/)**
|
|
69
|
+
|
|
70
|
+
To run the benchmarks locally, see [benchmark/README.md](benchmark/README.md).
|
|
67
71
|
|
|
68
72
|
## Usage
|
|
69
73
|
|
|
@@ -165,6 +169,15 @@ resp.encoding
|
|
|
165
169
|
resp.headers
|
|
166
170
|
resp.json()
|
|
167
171
|
resp.status_code
|
|
172
|
+
resp.reason_phrase # e.g. "OK", "Not Found"
|
|
173
|
+
resp.raise_for_status() # raise HTTPStatusError on non-2xx (returns self)
|
|
174
|
+
resp.is_informational # 1xx
|
|
175
|
+
resp.is_success # 2xx
|
|
176
|
+
resp.is_redirect # 3xx
|
|
177
|
+
resp.is_client_error # 4xx
|
|
178
|
+
resp.is_server_error # 5xx
|
|
179
|
+
resp.is_error # 4xx or 5xx
|
|
180
|
+
resp.has_redirect_location # 3xx with a Location header
|
|
168
181
|
resp.text
|
|
169
182
|
resp.text_markdown # html is converted to markdown text using html2text-rs
|
|
170
183
|
resp.text_plain # html is converted to plain text
|
|
@@ -172,6 +185,9 @@ resp.text_rich # html is converted to rich text
|
|
|
172
185
|
resp.url
|
|
173
186
|
```
|
|
174
187
|
|
|
188
|
+
`raise_for_status()` follows `httpx` semantics: any non-2xx status raises
|
|
189
|
+
`HTTPStatusError` (not just 4xx/5xx as in `requests`).
|
|
190
|
+
|
|
175
191
|
#### Streaming responses
|
|
176
192
|
|
|
177
193
|
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.
|
|
@@ -201,6 +217,9 @@ with client.stream("GET", url) as response:
|
|
|
201
217
|
|
|
202
218
|
**StreamingResponse attributes:**
|
|
203
219
|
- `status_code` - HTTP status code
|
|
220
|
+
- `reason_phrase` - Canonical reason phrase (e.g. "OK")
|
|
221
|
+
- `raise_for_status()` - Raise `HTTPStatusError` on a non-2xx status (returns self)
|
|
222
|
+
- `is_success` / `is_error` / `is_redirect` / ... - Status-class helpers (same as `Response`)
|
|
204
223
|
- `headers` - Response headers (case-insensitive)
|
|
205
224
|
- `cookies` - Response cookies
|
|
206
225
|
- `url` - Final URL after redirects
|
|
@@ -405,12 +424,11 @@ task httpbun:logs # Show container logs
|
|
|
405
424
|
| `docs` (build) | ✓ | | | |
|
|
406
425
|
| `linux`, `musllinux`, `windows`, `macos`, `sdist` | | | ✓ | ✓ |
|
|
407
426
|
| `release` (PyPI publish) | | | ✓ | ✓ |
|
|
408
|
-
| `benchmark` | | | ✓ | ✓ |
|
|
409
427
|
|
|
410
428
|
- **PRs**: Run lint, tests across Python 3.10-3.14 matrix, and verify docs build
|
|
411
|
-
- **Push to main**: Run tests
|
|
412
|
-
- **Tags**: Run tests, build wheels, publish stable release to PyPI
|
|
413
|
-
- **Manual**: Full multi-platform wheel builds with release
|
|
429
|
+
- **Push to main**: Run tests, then the separate `Benchmark` workflow runs the benchmark suite and publishes results to the [live benchmark charts](https://thomasht86.github.io/httpr/dev/bench/)
|
|
430
|
+
- **Tags**: Run tests, build wheels, publish stable release to PyPI
|
|
431
|
+
- **Manual**: Full multi-platform wheel builds with release
|
|
414
432
|
|
|
415
433
|
## Acknowledgements
|
|
416
434
|
|
|
@@ -83,6 +83,10 @@ response = client.get("https://api.example.com")
|
|
|
83
83
|
|
|
84
84
|
# Status
|
|
85
85
|
response.status_code # int: 200, 404, etc.
|
|
86
|
+
response.reason_phrase # str: "OK", "Not Found", etc.
|
|
87
|
+
response.is_success # bool: True for 2xx
|
|
88
|
+
response.is_error # bool: True for 4xx/5xx
|
|
89
|
+
response.raise_for_status() # raise HTTPStatusError on non-2xx (returns self)
|
|
86
90
|
|
|
87
91
|
# Body
|
|
88
92
|
response.text # str: decoded text
|