Resumable, cursor-based, CDN-safe HTTP downloads for Python
Project description
pyhaul
Resumable HTTP downloads for Python.
pip install pyhaul[requests] # or: httpx, niquests, urllib3, aiohttp (see below)
import requests
from pyhaul import haul
with requests.Session() as session:
result = haul("https://example.com/big.zip", session, dest="big.zip")
print(f"done: sha256={result.sha256[:16]}…")
What is it?
A small, pure-Python library that makes HTTP downloads resumable.
Call haul() with your existing HTTP client, a URL, and a destination
path — it handles byte-range negotiation, ETag validation, crash-safe
checkpointing, and atomic file completion. Sync and async; works with
requests, httpx, niquests, urllib3, and aiohttp (async).
Each call to haul() upholds these guarantees:
- The destination file is either complete or absent. There is no
state where a partially-written file sits at the final path.
Incomplete data lives in a temporary
.partfile; on completion it is atomically moved into place. - Interrupted downloads resume, not restart. Checkpoint state
lives on disk, not in memory. Kill the process, lose the network,
get a 503 — the next
haul()picks up from the last durable byte. Zero re-downloaded data if the resource hasn't changed. - Changed resources are detected, not silently corrupted. If
the remote file changes between attempts,
pyhauldetects the mismatch via ETag (a server-side fingerprint) and starts over cleanly instead of gluing mismatched halves together. - Your HTTP client is borrowed, not owned.
pyhaulsets per-request headers and returns the session untouched. It never creates, configures, or closes sessions. - Transport errors pass through unwrapped.
httpx.ReadTimeoutstayshttpx.ReadTimeout. You catch the types you already know.
How it fits into your code
One haul() = one HTTP request. It either succeeds and returns
CompleteHaul, or it throws — possibly after saving progress
to a .part file that allows the next call to resume. pyhaul never
creates sessions, connections, or clients. Your HTTP library's native
exceptions propagate through unwrapped, so you can drop haul()
into existing code without changing your error handling. Retries are
your call — a for-loop, tenacity, or nothing. Concurrency limiting
(e.g. asyncio.Semaphore) is also yours — pyhaul downloads one
file per call and doesn't manage parallelism.
def haul(url, client, *, dest, state=None) -> CompleteHaul: ...
async def haul_async(url, client, *, dest, state=None) -> CompleteHaul: ...
state is an optional HaulState bag, updated in-place as bytes
land on disk — works identically in sync and async. See
DESIGN.md for the exception hierarchy, transport
adapters, and download lifecycle.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyhaul-0.3.0.tar.gz.
File metadata
- Download URL: pyhaul-0.3.0.tar.gz
- Upload date:
- Size: 35.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
833586ddaedeabefa0fb27c58295555819e68aa0ed680302257c3986c40064ef
|
|
| MD5 |
b05a98dbf6ff445692d5dfc10100a6dc
|
|
| BLAKE2b-256 |
11a1e0936c385bda58e11e4bcffd2654da8e2acbe6ee507f8deeb1fa52708c19
|
Provenance
The following attestation bundles were made for pyhaul-0.3.0.tar.gz:
Publisher:
release.yml on chad-loder/pyhaul
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyhaul-0.3.0.tar.gz -
Subject digest:
833586ddaedeabefa0fb27c58295555819e68aa0ed680302257c3986c40064ef - Sigstore transparency entry: 1389429214
- Sigstore integration time:
-
Permalink:
chad-loder/pyhaul@f413fa3f6a9c1faa1899c37ade826f45c292c60c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/chad-loder
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f413fa3f6a9c1faa1899c37ade826f45c292c60c -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyhaul-0.3.0-py3-none-any.whl.
File metadata
- Download URL: pyhaul-0.3.0-py3-none-any.whl
- Upload date:
- Size: 45.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f93f13145923109ee299f5a4dae54cf91867a5d309ae442295ef870c8a80cc2
|
|
| MD5 |
96c05ca3a572e5a08765081e1db8c0a8
|
|
| BLAKE2b-256 |
317e9211c7eba4d9f62be6ab4f345877e289a49df16617310bd3e7db9b233c48
|
Provenance
The following attestation bundles were made for pyhaul-0.3.0-py3-none-any.whl:
Publisher:
release.yml on chad-loder/pyhaul
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyhaul-0.3.0-py3-none-any.whl -
Subject digest:
3f93f13145923109ee299f5a4dae54cf91867a5d309ae442295ef870c8a80cc2 - Sigstore transparency entry: 1389429327
- Sigstore integration time:
-
Permalink:
chad-loder/pyhaul@f413fa3f6a9c1faa1899c37ade826f45c292c60c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/chad-loder
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f413fa3f6a9c1faa1899c37ade826f45c292c60c -
Trigger Event:
push
-
Statement type: