chores: Implement unified response parser#32
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a Unified Response Parser
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Hello @KodeSage |
CLOSES #12
Description
This change introduces a single
_parse_responsefunction that every resource method can route HTTP responses through. It centralizes JSON decoding, success detection, and the mapping of HTTP status codes to the SDK's typed exception hierarchy, preventing per-resource error handling from drifting over time.Previously, response handling logic lived alongside the retry-aware
_raise_for_statushelper and operated on raw(status, headers, body)tuples._parse_responseprovides a clean, transport-agnostic entry point that takes anhttpx.Responseand either returns the decoded body or raises the correct typedexception with the raw body and status attached.
Behavior implemented:
AuthenticationError.InvalidRequestError, carrying field-level errors when theresponse body provides them.
NotFoundError.RateLimitError(parses theRetry-Afterheader).NetworkError(subject to retry by callers).HTTPError, so nothing escapes the funnel unhandled.carries a truthy
errorkey →ShadeError("Invalid response from API")/the extracted error message.
Every raised exception exposes both
status_codeand the rawresponse_body. Non-JSON error bodies still map to their typed exception with the raw body attached, and because all typed errors subclassShadeError, a malformed body never surfaces a rawJSONDecodeError.To support field-level validation errors,
InvalidRequestErrornow accepts and stores an optionalfield_errorsattribute (backward-compatible — existing construction calls are unaffected).Note on file naming: the proposed work referenced
http_client.py, but the actual HTTP module in this project issrc/shade/http.py(which already importshttpxas an optional dependency). The function was added there to avoidfragmenting the HTTP layer.
Dependencies: no new runtime dependencies.
httpxis already an optional dependency of the project; the type hint is declared as a string so the module continues to import cleanly whenhttpxis absent.Fixes # (issue)
Type of change
How Has This Been Tested?
A new test module,
tests/test_parse_response.py, exercises every acceptancecriterion against real
httpx.Responseobjects. The full existing suite wasalso run to confirm no regressions.
Reproduce locally:
Result: 91 passed (61 existing + 30 new).
{};non-dict JSON and
error-key bodies on 2xx are rejected.404, 429, 500/502/503/504, and other 4xx (e.g. 418).
error.fields) andtop-level (
errors) shapes;Nonewhen absent.ShadeErrorrather than a rawJSONDecodeError; non-JSON error bodies still map to the typed exception.response_bodyandstatus_codepresent on everyraised exception; message falls back to a sensible default when the body has none.
Test configuration: Python 3.11,
pytest,httpx0.28.1.Checklist:
Summary by CodeRabbit
New Features
Bug Fixes