Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- Phase-shortcut decorators `@before_request`, `@after_response`, `@on_error` for lifecycle hooks without authoring a full `Middleware` class. `@on_error` catches `Exception` only (so `asyncio.CancelledError` propagates); its handler may return a `Response` to recover or `None` to re-raise (Story 2.2).
- Request and Response immutability helper expansion: `Request.with_headers`, `with_cookie`, `with_cookies`, `with_extension`, `with_extensions`; `Response.with_headers`, `with_status`. Plural helpers merge mappings (incoming keys override existing); singular helpers add or replace a single entry. No validation, no header-key normalization — matches the existing `with_header` semantics from Story 1.2 (Story 2.3).
- `MsgspecDecoder` opt-in `ResponseDecoder` adapter behind the `[msgspec]` extra at `httpware.decoders.msgspec`; `msgspec.json.decode(content, type=model)` in a single C-level parse pass. Accepts `msgspec.Struct`, dataclasses, attrs, NamedTuples, TypedDicts, and builtin/container types as `model` (pydantic models use `PydanticDecoder` instead). `msgspec.ValidationError` and `msgspec.DecodeError` propagate unchanged. Module import is safe without the extra (gated by `httpware._internal.import_checker.is_msgspec_installed`); only `MsgspecDecoder()` construction raises `ImportError` with an install hint when the extra is missing. `import httpware` does NOT eagerly load `msgspec` — `MsgspecDecoder` is reachable only via `from httpware.decoders.msgspec import MsgspecDecoder` (Story 1.6).
- `AsyncClient` — the v0.1.0 public surface. Construct with keyword-only `base_url`, `default_headers`, `default_query`, `timeout` (accepts `Timeout` instance, float seconds, or `None`), `limits`, `transport` (defaults to `Httpx2Transport`), `decoder` (defaults to `PydanticDecoder`), and `middleware` (`Sequence[Middleware]`, composed via `httpware._internal.chain.compose` at construction). Eight HTTP method shortcuts (`get`, `post`, `put`, `patch`, `delete`, `head`, `options`, `request`) with `@typing.overload`-based `response_model` typing — passing `response_model=type[T]` returns `T`, otherwise `Response`. Per-call overrides for `headers`, `params`, `cookies`, `timeout`; body params `json` (auto-encoded with `Content-Type: application/json`, typed as `JsonValue` recursive alias) and `content` (raw bytes; mutually exclusive). `base_url` joins with the path using an httpx-style prefix; absolute URLs (`http(s)://`) bypass. `from_url(base_url, **kwargs)` classmethod factory. Async context-manager lifecycle: the original client owns the transport and closes it on `__aexit__`; views returned by `with_options(**overrides)` share the transport and are no-ops on close. `with_options` accepts a keyword allowlist (`base_url`, `default_headers`, `default_query`, `timeout`, `decoder`, `middleware`); `limits` and `transport` are not overridable. Out of scope and deferred: `auth=` (Story 2.4), `data=`/`files=` body params, transport reference-counting, streaming (Epic 4), observability (Epic 5) (Story 1.7).

[Unreleased]: https://github.com/modern-python/httpware/commits/main
Loading
Loading