0.3.0 — pydantic as an optional extra
Breaking changes
pydanticis no longer a required dependency. It moved from[project] dependenciesto[project.optional-dependencies]. Install it explicitly:pip install httpware[pydantic]. Thehttpware[all]extra continues to include it.httpware.PydanticDecoderis no longer re-exported from the top-level package. Import directly from the submodule:from httpware.decoders.pydantic import PydanticDecoder. This mirrors the existingMsgspecDecoderimport path.AsyncClient()withdecoder=Noneand no pydantic extra raisesImportErrorat__init__. Passdecoder=MsgspecDecoder()or installhttpware[pydantic]to keep the default behavior.
Other changes
tests/test_decoders_pydantic.pyadds parametrized payload-edge tests that pin current pydantic-core behavior forb"",b"null",b"{}", malformed JSON, and invalid UTF-8.tests/test_optional_extras_isolation.pynow covers both pydantic and msgspec via fresh-subprocessimport httpwarechecks.- README freshness pass: status line corrected from "0.1.0 alpha" to "0.3.0"; post-pivot framing replaces the pre-pivot description;
RecordedTransportreference removed.
Migration
# 0.2.0
from httpware import AsyncClient, PydanticDecoder
async with AsyncClient(base_url="https://api.example.com") as client:
user = await client.get("/users/1", response_model=User)# 0.3.0 — option 1: install the extra, code unchanged
# pip install httpware[pydantic]
from httpware import AsyncClient
async with AsyncClient(base_url="https://api.example.com") as client:
user = await client.get("/users/1", response_model=User)
# 0.3.0 — option 2: import PydanticDecoder from the submodule
from httpware import AsyncClient
from httpware.decoders.pydantic import PydanticDecoder
async with AsyncClient(decoder=PydanticDecoder()) as client:
user = await client.get("/users/1", response_model=User)What's next
Epic 3 (resilience middleware — retry, timeout, bulkhead) and Epic 5 (observability) ship in subsequent releases. See planning/engineering.md §8.