googleapis / googleapis/python-genai
TypeError in convert_if_exist_pydantic_model with parameterized generic types
- Dominant language
- Python
- Stars
- 4k
- Forks
- 1k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 40
Description
## Description
When automatic function calling processes a function with a parameterized generic type annotation (e.g., `set[str]`), the SDK raises `TypeError: isinstance() argument 2 cannot be a parameterized generic`.
### Note
Apologies, my agent posted before I got to review this, but it seems mostly fine.
## Minimal Reproduction
```python
from google.genai._extra_utils import convert_if_exist_pydantic_model
# Simulating what happens when Gemini returns a value for a set[str] parameter
result = convert_if_exist_pydantic_model(
value=['a', 'b'], # Gemini returns list (JSON array)
annotation=set[str], # But annotation is set[str]
param_name='items',
func_name='my_func'
)
# TypeError: isinstance() argument 2 cannot be a parameterized generic
```
## Cause
In `_extra_utils.py`, the function `convert_if_exist_pydantic_model()` has two locations where `isinstance()` is called with an annotation that could be a `GenericAlias`:
**Line 257** (inside Union handling):
```python
or isinstance(value, arg)
```
**Line 279** (final fallback):
```python
if not isinstance(value, annotation):
```
In Python, `isinstance(x, set[str])` raises `TypeError` because `set[str]` is a `GenericAlias`, not a type. The SDK correctly handles `list[T]` and `dict[K,V]` with special cases using `get_origin()`, but other parameterized generics fall through to the raw `isinstance()` call.
## Affected Versions
- google-genai 1.60.0
- google-genai 1.61.0
## Environment
- Python 3.12
- Linux
## Proposed Fix
Add a helper function that safely handles parameterized generics:
```python
def _safe_isinstance(value: Any, annotation: Any) -> bool:
"""Check isinstance, handling GenericAlias types like set[str]."""
origin = get_origin(annotation)
if origin is not None:
return isinstance(value, origin)
try:
return isinstance(value, annotation)
except TypeError:
return False
```
Then replace:
- Line 257: `isinstance(value, arg)` → `_safe_isinstance(value, arg)`
- Line 279: `isinstance(value, annotation)` → `_safe_isinstance(value, annotation)`
This follows the same pattern already used for `list[T]` and `dict[K,V]` at lines 239 and 245.
Contributor guide
Assessment
This issue has not been assessed yet.