fix: Raise for missing DeepAttrDict keys instead of inserting them - #643
Merged
Merged
Conversation
razor-x
force-pushed
the
claude/python-sdk-audit-o2iid9-10-deep-attr-dict
branch
from
August 28, 2026 19:30
d27b83d to
1c3d417
Compare
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY
razor-x
force-pushed
the
claude/python-sdk-audit-o2iid9-10-deep-attr-dict
branch
from
August 28, 2026 20:43
1c3d417 to
1e56f51
Compare
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.
What
DeepAttrDict— the type behindcustom_metadataon devices, connected accounts, phones, connect webviews, and events, and the fallback for unknown event/action-attempt variants — silently auto-vivified on read:device.custom_metadata.reservaton_idreturned{}and wrote the typo'd key into the resource, which then re-serialized back to the API on the next update (SDK audit finding M9, runtime-verified).MIGRATION.mdclaimed this exact v1 footgun was fixed.KeyErrorwhen indexing,AttributeErrorfor attribute access — matching the typed resource dataclasses and what MIGRATION.md already promises.__getattr__translatesKeyErrortoAttributeErrorsohasattr,getattr(..., default), and copy/pickle protocol probes behave normally..get(),in, and iteration remain the probes for optional keys.MIGRATION.md's misleading "custom_metadata... not affected" line now states the raising behavior and the.get()probe pattern.custom_metadatakeys via bare attribute access and truthy-checked the{}must switch to.get("key")— the pattern the migration guide already prescribes for typed resources.Testing
Extended
test/deep_attr_dict_test.py(previously a single 7-line happy path): missing key raisesKeyError/ missing attribute raisesAttributeError; reads never insert;hasattr/getattr-default/.get/inall behave; nested wrapping intact; end-to-end — a typo'dcustom_metadataread on a hydrated device raises and leaves the metadata unmutated; unknown-event fallback fields stay readable.Revert check: with
seam/deep_attr_dict.pyreverted to main, the tests fail withDID NOT RAISE AttributeError— the silent-vivification symptom.Full suite: 192 passed; mypy, pylint (10.00), black clean.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY
Generated by Claude Code