From adf6a00725763da24003fd24d586a1c30ec0df34 Mon Sep 17 00:00:00 2001 From: devteamaegis Date: Sun, 31 May 2026 18:45:04 -0400 Subject: [PATCH] fix(_utils/_transform): guard against IndexError for bare dict annotation When a TypedDict field is annotated with a bare `dict` (no type parameters), `get_args(dict)` returns an empty tuple and the previous unconditional `get_args(stripped_type)[1]` raised IndexError. Guard with `args = get_args(stripped_type)` and only recurse into the value type when `len(args) >= 2`; otherwise return the data unchanged. Same fix applied to `_async_transform_recursive`. --- src/openai/_utils/_transform.py | 14 ++++++++++---- tests/test_transform.py | 13 +++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/openai/_utils/_transform.py b/src/openai/_utils/_transform.py index 414f38c340..6061e38c3e 100644 --- a/src/openai/_utils/_transform.py +++ b/src/openai/_utils/_transform.py @@ -180,8 +180,11 @@ def _transform_recursive( return _transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): - items_type = get_args(stripped_type)[1] - return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + args = get_args(stripped_type) + if len(args) >= 2: + items_type = args[1] + return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + return data if ( # List[T] @@ -346,8 +349,11 @@ async def _async_transform_recursive( return await _async_transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): - items_type = get_args(stripped_type)[1] - return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + args = get_args(stripped_type) + if len(args) >= 2: + items_type = args[1] + return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + return data if ( # List[T] diff --git a/tests/test_transform.py b/tests/test_transform.py index bece75dfc7..4f50799572 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -458,3 +458,16 @@ async def test_strips_notgiven(use_async: bool) -> None: async def test_strips_omit(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} assert await transform({"foo_bar": omit}, Foo1, use_async) == {} + + +class TypedDictBareDict(TypedDict): + metadata: dict # bare dict, no type parameters + + +@parametrize +@pytest.mark.asyncio +async def test_bare_dict_no_indexerror(use_async: bool) -> None: + # bare `dict` annotation (no type params) must not raise IndexError + assert await transform({"metadata": {"key": "value"}}, TypedDictBareDict, use_async) == { + "metadata": {"key": "value"} + }