serp-fang (Fang)
Fang is Serpentine's synchronous HTTP(S) client — the httpx equivalent. It is layered like the Rust HTTP stacks: a native transport core (serp-socket: std::net + system TLS — schannel on Windows, OpenSSL on Linux/macOS) with a thin pure-Serpentine façade that mirrors httpx names and behavior. The same source dual-runs under CPython (ssl module).
from serp_fang import Client, Response, client, get, post
r: Response = get("https://example.com/")
print(r.status_code, r.header("content-type"))
print(r.text())
r.raise_for_status()
p: Response = post("https://api.example/items", b'{"name": "fang"}',
content_type="application/json")
j = p.json()
c: Client = client("https://api.example", timeout=10.0, follow_redirects=True)
c.set_basic_auth("user", "secret")
r2: Response = c.get("/items")
httpx-equivalent API
Top-level verbs (each takes timeout=5.0, follow_redirects=False, verify=True
keywords, matching httpx defaults):
get / head / options / delete (url, ...)—getalso takesauth_user/auth_passpost / put / patch (url, content, content_type=...)— raw-body variantspost_form(url, form)— httpxdata=...post_json(url, payload)— httpxjson=...(payload is a dynamic PyVal)post_multipart(url, fields, files, boundary="")— httpxfiles=...withFilePartrequest(method, url, ...)— bodyless generic requeststream(method, url, ...) -> ResponseStream— httpxstream:read()chunks,close()download(url, path, ...)— streams a body straight to disk (constant memory)upload_file(method, url, path, content_type=...)— file body, wire-chunked sends- helpers:
with_params(url, params)(httpxparams=...),basic_auth(user, pw),build_multipart,multipart_content_type,header_value,parse_response,decode_chunked
Client (httpx.Client): base_url, default headers, persistent cookies
jar, timeout, follow_redirects, max_redirects, verify, basic auth;
methods mirror the verbs plus stream/download/upload_file/set_header/
set_cookie/set_basic_auth/close. Create with client(...) (kwargs like
httpx.Client).
Response (httpx.Response): status_code, reason_phrase, http_version,
url (final URL after redirects), headers, content, history
(pre-redirect URLs), elapsed; methods text(), json(), header(name),
cookies(), is_success()/is_redirect()/is_client_error()/is_server_error()/
is_error()/is_informational(), has_redirect_location(),
raise_for_status() (raises HTTPStatusError).
Behavior parity with httpx:
- https with SNI + system trust roots;
verify=Falseopt-out; cert failures raiseOSError("certificate verify failed"). - Redirects (when
follow_redirects=True): 301/302/303 convert to GET and drop the body (307/308 preserve), Location is resolved withurljoin, authorization is stripped on cross-host hops,TooManyRedirectspastmax_redirects. - Cookies:
set-cookieresponses populate the client jar and are replayed. accept-encoding: gzipis sent and gzip/deflate bodies decode transparently (streams requestidentityinstead).- Content-Length and chunked framing, incremental in
ResponseStream.
Divergences from httpx (language subset)
- Properties are methods:
r.text(), notr.text. - kwargs that take lists/dicts/bytes in httpx are explicit parameters or
Clientfields (defaults may only be scalar literals). - One connection per request (
connection: close) — no pooling/keep-alive, no HTTP/2, no proxies. text()decodes UTF-8 (no charset sniffing).- Transport errors are the normalized serp-socket
OSErrors ("connection refused", "timed out", "tls handshake failed", ...).
Async (AsyncClient, D45)
async with AsyncClient(base_url="http://127.0.0.1:8000", timeout=5.0) as client:
r: Response = await client.get("/items/1")
AsyncClient runs the same engine over sockets in async mode: every would-block
suspends only the calling task, so asyncio.gather of several requests overlaps them
(four 300 ms requests complete in ~0.3 s natively). Methods: request/get/head/options/ delete/post/put/patch/post_form/post_json/stream/aclose, set_header/set_basic_auth/ set_cookie, async with. Divergences: stream() returns a ResponseStream whose
read() is a plain (cooperative) call — no aiter_bytes; connects/TLS handshakes are
still blocking; under CPython the async mode is a no-op, so requests there run one at a
time.
Metadata
Release files for serp-fang 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| serp_fang-0.3.1.tar.gz | 13.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| serp_fang-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.7 kB
Release files / serp_fang-0.3.1.tar.gz
| Download URL | serp_fang-0.3.1.tar.gz |
|---|---|
| Size | 13.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0286d3ec6604c964bdbc4bbaac585ab88c40ebbf8a7e9feed0d037b851799959
|
|
BLAKE2b-256 checksum How to use checksums |
dacb6b27df13f7c4c51d35fc654cb5b750a783cc76a67972e05b3e67beff1bf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / serp_fang-0.3.1-py3-none-any.whl
| Download URL | serp_fang-0.3.1-py3-none-any.whl |
|---|---|
| Size | 11.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
441d020f5a4996c09b7b49a35e8bc4a0378418971533dd662d9d124d7b637d6a
|
|
BLAKE2b-256 checksum How to use checksums |
0b5234bade2f2ecbf9dde8b731ac6f251267e2fd128a8f7321f49ce6f8b0841e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log