fix: guard against bare unparameterized dict/list in construct_type and transform#1639
Open
kiankhooban wants to merge 2 commits into
Open
fix: guard against bare unparameterized dict/list in construct_type and transform#1639kiankhooban wants to merge 2 commits into
kiankhooban wants to merge 2 commits into
Conversation
…nd transform get_args(dict) and get_args(list) return empty tuples when no type parameters are present. Four sites were unconditionally indexing into those tuples, crashing with ValueError or IndexError. - _models.py: use already-computed `args` with len-guard for dict branch; add `if args` guard for list branch - _utils/_transform.py: guard both sync and async dict branches Fixes anthropics#1619, anthropics#1626, anthropics#1628
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates type-transformation utilities to handle unparameterized container annotations (e.g., dict / Dict without type args) more safely by defaulting inner types to object instead of indexing missing get_args() entries.
Changes:
- Guard
get_args()indexing for dict value types in recursive transform helpers. - Guard
get_args()indexing for dict/list inner types inconstruct_type.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/anthropic/_utils/_transform.py | Prevents IndexError when transforming dict-like data against dict annotations without type parameters. |
| src/anthropic/_models.py | Makes construct_type robust to missing generic args for dict and list annotations by falling back to object. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
350
to
352
| _args = get_args(stripped_type) | ||
| items_type = _args[1] if len(_args) >= 2 else object | ||
| return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} |
Comment on lines
+183
to
+184
| _args = get_args(stripped_type) | ||
| items_type = _args[1] if len(_args) >= 2 else object |
- Rename _args to args for consistency with rest of codebase - Fix pre-existing bug: async dict branch was calling _transform_recursive instead of _async_transform_recursive, skipping async recursion for nested dict values; switch to await _async_transform_recursive
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.
get_args(dict)andget_args(list)return empty tuples when no type parameters are present. Four sites were unconditionally indexing into those tuples, raisingValueErrororIndexErrorwhen a model field is annotated as a baredictorlistinstead ofDict[K, V]orList[T].Crash sites fixed
src/anthropic/_models.pyconstruct_type:_, items_type = get_args(type_)→ValueErroron baredict(issue BUG: construct_type() crashes with ValueError when type_ is a bare dict #1619)construct_type:inner_type = args[0]→IndexErroron barelist(issue BUG: construct_type() raises IndexError when called with bare unparameterized list #1626)src/anthropic/_utils/_transform.py_transform_recursive(sync):get_args(stripped_type)[1]→IndexErroron baredict(issue IndexError on bare (unparameterized) dict annotation in _transform_recursive #1628)_async_transform_recursive: same pattern, same fixFix
Guard each index access with a length check and fall back to
objectwhen no type args are present — preserving the value as-is, which is the correct behaviour for unparameterized containers.Reproduction
Fixes #1619, #1626, #1628