Extract _DecoderResolver for Seam B#77
Merged
Merged
Conversation
Full-lane design.md + plan.md for extracting a _DecoderResolver (+ generic _BoundDecoder) behind Seam B, collapsing the 4-site resolve/raise/decode/ wrap smear in client.py. Design only — no source changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the 4-site resolve/raise/decode/wrap smear in client.py behind one _DecoderResolver (+ generic _BoundDecoder) in decoders/_resolver.py. resolve() returns a _BoundDecoder sealing decoder+model together; the four send/ send_with_response sites collapse to resolve -> dispatch -> bound.decode. Both clients keep self._decoders and gain self._decoder_resolver; both _dispatch_decoder methods removed. Behaviour byte-identical. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Direct decision-matrix tests for the resolver — no client, no MockTransport: resolve->bound->decode, no-claimer MissingDecoderError with registered_names + ordering, empty-tuple names, first-match-wins, and decode failure wrapped as DecodeError with response/model/original/__cause__. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update Seam B contract in architecture/decoders.md: resolution + pre-flight MissingDecoderError live in _DecoderResolver.resolve; DecodeError wrapping in _BoundDecoder.decode. Replaces the _dispatch_decoder / send-wraps framing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deepening candidate #3 from the architecture review.
Problem
The decoder seam (Seam B) is real — pydantic + msgspec adapters — but the logic for using it was copy-pasted across four
send/send_with_responsemethods on the two clients (client.py:185, 213, 1200, 1228): walk_decoders, raiseMissingDecoderError(registered_names=…)pre-flight if none claims the model, thendecoder.decode(...)wrapping failures asDecodeError. Plus_dispatch_decoderdefined twice.Change
One
_DecoderResolver(+ generic_BoundDecoder) in a newdecoders/_resolver.pyowns it:resolve(model) -> _BoundDecoder[T]— firstcan_decodewins; none →MissingDecoderError(pre-flight, before the HTTP call)._BoundDecoder.decode(response) -> T— wrapsexcept ExceptionasDecodeError, with the decoder + model sealed together so a mismatch is unrepresentable.The four sites collapse to
resolve → dispatch → bound.decode. Both clients keepself._decoders(tested attribute) and gainself._decoder_resolver; both_dispatch_decodermethods removed. Fully synchronous → one resolver serves both clients. Behaviour byte-identical.Tests
tests/test_decoder_resolver.pydrivesresolve/bound.decodedirectly: resolution,MissingDecoderErrorwithregistered_names+ ordering, first-match-wins,DecodeErrorwrapping.Verification
just lintclean (ruff + ty),just test→ 723 passed, 100% coveragegrep -rE 'httpx2\._' src/httpware/cleanDesign bundle:
planning/changes/2026-06-23.02-decoder-resolver-extraction/. Promoted intoarchitecture/decoders.md.🤖 Generated with Claude Code