fix: limit response parsing to values the SDK does not recognize - #653
Merged
Conversation
#651 conflated two things. Handling values the SDK does not recognize -- new event types, action types, error codes, enum values -- was already on main before it, and is what forward compatibility needs. What #651 added on top was tolerance for payloads that are malformed rather than merely new: a list sent as a scalar, an object sent as a string, a payload that is not an object. That is not forward compatibility, it is a defect being swallowed. A null list was already read as empty, so the new guards only caught genuinely broken data and turned it into an empty list or None. Worse, catching exceptions around a known variant meant one bad field silently downgraded a typed event to an untyped DeepAttrDict, with nothing to tell the caller why the type changed. Removes seam/parse.py, the isinstance guards in every from_dict, and the exception handling around known variants. The unrecognized-discriminator fallback that predates #651 is untouched, so unknown event types still yield a DeepAttrDict, unknown error codes still fall back per item, and unknown enum values still read as themselves. SeamActionAttemptUnknownStatusError stays. The action attempt contract is strict: waiting promises a succeeded attempt or a raise, and returning an unrecognized status as a success reports something the SDK cannot vouch for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M2kJ4nGaM8imZCVMEKjmXA
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.
Partially reverts #651.
Why
#651 conflated two different things:
mainbefore feat: Improve API response parsing resilience to unknown fields #651.#651 added tolerance for the second, which was not the goal and is actively harmful:
None.DeepAttrDict, with nothing to tell the caller why the type changed.What this removes
seam/parse.pyif not isinstance(d, dict): d = {}guard in every generatedfrom_dictWhat this keeps
The unrecognized-value handling that predates #651 is untouched:
event_typeDeepAttrDicterror_code/warning_codedevice.device_type == "future_lock")action_type/statusstatusreads as itselfSeamActionAttemptUnknownStatusErroralso stays. The action attempt contract is strict: waiting promises a succeeded attempt or a raise, and the previous behavior returned an unrecognized status as a success, typedSuccessActionAttempt— telling the caller the action completed when the SDK cannot tell.Tests
test/total_parsing_test.pyis replaced bytest/forward_compatibility_test.py, which pins only the rule that survives: the SDK does not explode on values it does not recognize. The tests that asserted malformed-payload tolerance are gone with the behavior.278 tests, mypy clean, pylint 10.00, black clean.
Note
raw_json()on the webhook event is not in this PR. It follows separately.🤖 Generated with Claude Code
https://claude.ai/code/session_01M2kJ4nGaM8imZCVMEKjmXA
Generated by Claude Code