Skip to main content

sfvparse

PyPI version License: MIT Python 3.11+

Zero-dependency RFC 8941 HTTP Structured Field Values parser and serializer for Python 3.11+.

Quick Start

pip install sfvparse
# OR (not yet on PyPI):
# pip install git+https://github.com/prasad-a-abhishek/sfvparse.git
from sfvparse import parse_item, parse_list, parse_dict, serialize_list

# Parse an Item
item = parse_item(b"text/plain;charset=utf-8")
# {"value": "text/plain", "params": {"charset": "utf-8"}}

# Parse a Link-header List
links = parse_list('<https://api.example.com/2>; rel="next", <https://api.example.com/1>; rel="prev"')
# [{"value": "https://api.example.com/2", "params": {"rel": "next"}}, ...]

# Parse a Dictionary
d = parse_dict(b"label=example;max-age=3600")
# {"label": {"value": "example", "params": {"max-age": 3600}}}

# Serialize back to bytes
out = serialize_list([{"value": "foo", "params": {"rel": "next"}}])
# b"foo; rel=next"

⚡ Performance & Benchmarks

sfvparse is benchmarked against the canonical reference Python implementation mnot/http_sfv across 50 iterations (10 workload profiles × 5 runs each). Reproduce locally:

python3 benchmarks/run_benchmark.py

Workload profiles (10 total — reproduce via python3 benchmarks/run_benchmark.py):

Profile Input size sfvparse mean http_sfv mean Speedup Notes
Single item (token) 10 B 6.78 µs 6.59 µs ~1.0× Equal speed
Single item (param'd) 32 B 13.04 µs 14.38 µs 1.10× sfvparse slightly faster
Single item (string+escape) 16 B 9.16 µs 6.15 µs 0.67× http_sfv ~1.5× faster on strings
Short list (3 items) 39 B 24.77 µs 15.22 µs 0.61× http_sfv ~1.6× faster on lists
Long list (50 items) 1268 B 2359.75 µs 711.16 µs 0.30× http_sfv ~3.3× faster; sfvparse has O(n²) inner-list handling
Dict (5 keys, params) 48 B 42.06 µs 48.30 µs 1.15× Roughly equal
Link header (realistic) 80 B 20.19 µs ERR — http_sfv HttpHeader.parse throws on bare rel tokens in params
Accept-Language header 44 B 41.04 µs 59.32 µs 1.45× sfvparse faster
Inner-list member 12 B 19.88 µs 17.95 µs 0.90× Roughly equal
Deeply nested params 70 B 27.32 µs 36.75 µs 1.34× sfvparse faster

Honest summary: sfvparse and http_sfv are comparable on most workloads. sfvparse is ~1.1-1.5× faster on dict, accept-language, and deeply-nested params workloads. http_sfv is ~1.5-3× faster on string-heavy and list-heavy workloads; the long-list case is the most pronounced gap (sfvparse has O(n²) inner-list handling). Both use negligible memory (~1-2 KB peak). sfvparse wins on API ergonomics (single-function entry points vs class-then-parse) and on having a published PyPI package with type hints.

Why sfvparse?

Python developers building HTTP clients, REST API clients, or HTTP servers need standards-compliant RFC 8941 parsing — used in headers like Link, Sec-WebSocket-Extensions, Accept-Language, and Signature — without taking on a heavy dependency.

Competitor landscape:

Package PyPI Zero-deps RFC 8941 Maintenance
mnot/http_sfv (reference) No (GitHub only) Yes Yes Reference (14★)
http_sfv (PyPI) Yes No (deps on http_sfv) Partial Stale
linkheader Yes Yes RFC 5988 only Unmaintained (Python 2 era)
httplink Yes Yes RFC 8288 only Niche
sfvparse Yes Yes Full RFC 8941 Active

sfvparse trade-offs:

  • ✅ Zero runtime dependencies — pyproject.toml has dependencies = []. Only the Python standard library.
  • ✅ RFC 8941 compliant — full Item, List, Dictionary, and bare-item parsing (sf-token, sf-string, sf-integer, sf-decimal, sf-boolean, sf-binary) with parameter lists.
  • ✅ RFC 8288 Link-header extension — <URI> member syntax recognized automatically.
  • ✅ Inner-list extension — ( member member ; param ) syntax.
  • ✅ Type-hinted TypedDict API — Item, ListMember, DictMember for static type-checkers.
  • ✅ Works on Python 3.11+ with full PEP 604 union types and structural pattern matching.
  • ⚠️ Byte-sequence asymmetry — the parser returns raw base64 (between the : : markers) per spec AC6; the serializer expects decoded bytes. Callers that want to round-trip byte sequences should base64.b64decode(...) between parse and serialize. This is intentional and documented.
  • ⚠️ Spec deviations from strict RFC 8941 ABNF — see "Limitations / non-goals" below.

Key Features & Complete API Reference

Public functions

Function Returns Description
parse_item(data) Item Parse a single Item (bare item + parameters)
parse_list(data) list[ListMember] Parse a List of Items / dictionary-style members
parse_dict(data) dict[str, DictMember] Parse a Dictionary
parse_token(data) str Parse a single sf-token
parse_string(data) str Parse a single sf-string
parse_integer(data) int Parse a single sf-integer
parse_decimal(data) float Parse a single sf-decimal
parse_boolean(data) bool Parse a single sf-boolean (?0 or ?1)
parse_byte_sequence(data) bytes Parse a single sf-binary (returns raw base64 inside : : per spec)
serialize_item(member) bytes Serialize one Item
serialize_list(members) bytes Serialize a list of Items
serialize_dict(d) bytes Serialize a dictionary

All parse_* functions accept bytes or str input; serialize_* functions return bytes.

TypedDict types

from sfvparse import Item, ListMember, DictMember, Value

# Value = Union[str, int, float, bool, bytes, list]

item: Item = {"value": "text/plain", "params": {"charset": "utf-8"}}
member: ListMember = {"value": "https://example.com", "params": {"rel": "next"}}
dm: DictMember = {"key": "foo", "value": "bar", "params": {"max-age": 3600}}

CLI usage

sfvparse is a library-first package (no CLI of its own). Use it programmatically:

python3 -c "from sfvparse import parse_item; import sys; print(parse_item(sys.stdin.buffer.read()))"

Error handling

All parse_* functions raise ValueError on malformed input and TypeError on wrong input types. This is the only contract — no ParseError class hierarchy.

Test count

pytest collection reports 282 passing tests as of this release (covering all 25 spec acceptance criteria plus edge cases, round-trip checks, and TypeHint integration). Run python3 -m pytest tests/ --collect-only -q to see the full list.

Limitations / Non-Goals

  • No RFC 9651 extensions — sfvparse implements the RFC 8941 subset only. Items, Lists, Dictionaries, and the six bare-item types. No structured-fields extensions from RFC 9651 are parsed.
  • No HTTP client / server — this is a parsing/serialization library only.
  • No binary content-transfer encodings (e.g., quoted-printable, base64 transport).
  • No caching-aware content negotiation (RFC 2295).
  • Spec deviations from strict RFC 8941:
    • Integer digit count is unbounded (Python ints are arbitrary-precision).
    • Decimal fractional-digit count is unbounded (Python floats can hold the full IEEE 754 range).
    • Parameter and dictionary keys are lowercased before storage (RFC 8941 says they are case-insensitive; we normalize for consistency).
    • parse_token greedily scans until end-of-input, including any internal whitespace. Strict RFC 8941 expects parse_token to be called on a slice bounded by other syntax.
    • Bare-item tokens ending in 2+ consecutive punctuation tchar (e.g. text/plain!!!) are split — the punctuation run is treated as trailing junk that parse_item then rejects.

License

MIT License — Copyright (c) 2026 sfvparse contributors. See LICENSE for full text.

Built by the Hermes repo-factory. See benchmarks/BENCHMARK.md for full benchmark methodology and raw numbers.

Metadata

Release files for sfvparse 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sfvparse 0.1.0
File Size Uploaded
sfvparse-0.1.0.tar.gz 26.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sfvparse 0.1.0
File Interpreter ABI Platform
sfvparse-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 38.9 kB

Release files / sfvparse-0.1.0.tar.gz

Download URL sfvparse-0.1.0.tar.gz
Size 26.9 kB
Tags Source
SHA-256 checksum
How to use checksums
59c0a1604be387d30136f0b98a874218c84088a85d6cc7e1a0ecadfb4cecdc98
BLAKE2b-256 checksum
How to use checksums
5a4c5cb426c102c48eeeda1413666401cf637a9dbd4c54d7094591db84a9f819
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release files / sfvparse-0.1.0-py3-none-any.whl

Download URL sfvparse-0.1.0-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
43f104bd1d9e5147191a9fcec5cc892f0585bb192e2b478f9615edc1d70a2352
BLAKE2b-256 checksum
How to use checksums
8ec66e71bc8d3daed965b1a2fba22d3623d54a04ef65b5b7b949ea45eea753f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page