Commit b147e2c
feat(story-1.3): exception hierarchy with plain typed fields
Status-keyed exception hierarchy with plain typed fields under
`src/httpware/errors.py`: `ClientError` root; `TransportError` and
`TimeoutError` direct subclasses; `StatusError` with kwargs-only
6-field `__init__` and a redacting `__repr__`; `ClientStatusError` and
`ServerStatusError` category bases; 9 status-leaf classes
(`BadRequestError` 400 … `ServiceUnavailableError` 503);
`STATUS_TO_EXCEPTION` lookup dict.
Adversarial code review (Blind + Edge Case + Acceptance Auditor) flagged
seven decisions; six landed as in-scope patches, one accepted as v0:
- `StatusError.__reduce__` makes exceptions picklable / deep-copyable
across process boundaries (multiprocessing, pytest-xdist, Sentry).
- `__repr__` and the `Exception.__init__` summary message strip
`user:pass@` userinfo from the request URL to close the NFR8 leak path;
query-string redaction stays with Story 5.3's `Redactor`.
- `TimeoutError` multi-inherits `(ClientError, builtins.TimeoutError)` so
`except builtins.TimeoutError` (asyncio.wait_for's form) also catches
httpware-raised timeouts. Revisits architecture Decision 3.
- Module docstring + `STATUS_TO_EXCEPTION` comment scope the fallback
rule to `400 <= status < 600`; callers must guard non-error statuses
(1xx/2xx/3xx) before consulting the dict.
- `headers` is stored as a read-only `MappingProxyType(dict(headers))`
so caller mutations after `raise` cannot bleed into the exception.
- Story Dev Notes canonical `__all__` updated to match the RUF022 order
ruff enforces in CI.
43 tests in `tests/test_errors.py` (29 from the original story spec + 14
from the review patches); 70/70 project-wide pass; coverage 100% on
`errors.py` and every other module. `just lint` clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 805fcd0 commit b147e2c
6 files changed
Lines changed: 983 additions & 1 deletion
File tree
- docs
- stories
- src/httpware
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
5 | 11 | | |
6 | 12 | | |
7 | 13 | | |
| |||
0 commit comments