failed NO_PATCH NO_PATCH UNSUBMITTED empty_patch(None) · None tool calls · 0 s · fastapi/fastapi
🐛 Fix optional sequence handling in `serialize sequence value` with Pydantic V2
Currently the following test code leads to `TypeError: issubclass() arg 1 must be a class` (with Python 3.14 error is different, but the root cause is the same):
```py
from typing import List, Optional
from fastapi import FastAPI, File
from fastapi.testclient import TestClient
app = FastAPI()
@app.post("/files")
async def upload_files(files: Optional[List[bytes]] = File(None)):
if files is None:
return {"files_count": 0}
return {"files_count": len(files), "sizes": [len(f) for f in files]}
def test_optional_bytes_list():
client = TestClient(app)
response = client.post(
"/files",
files=[("files", b"content1"), ("files", b"content2")],
)
assert response.status_code == 200
assert response.json() == {"files_count": 2, "sizes": [8, 8]}
```
This is because for optional sequence the `origin_type` in the following line is `Union`:
https://github.com/fastapi/fastapi/blob/972a967d5d3fa24d450637c36c6b7ad1f1d8c1b6/fastapi/_compat/v2.py#L374
So, we need to unwrap that `Uinion`, take non-None type from its arguments and use it as `origin_type`| # | Tool | Arguments | Result |
|---|---|---|---|
| No trace captured. | |||
.s......F
=================================== FAILURES ===================================
_______________ test_serialize_sequence_value_with_optional_list _______________
@needs_pydanticv2
def test_serialize_sequence_value_with_optional_list():
"""Test that serialize_sequence_value handles optional lists correctly."""
from fastapi._compat import v2
field_info = FieldInfo(annotation=Union[List[str], None])
field = v2.ModelField(name="items", field_info=field_info)
> result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_compat.py:146:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
fastapi/_compat/v2.py:374: in serialize_sequence_value
assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/typing.py:1692: in __subclasscheck__
return issubclass(cls, self.__origin__)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'collections.abc.Sequence'>, subclass = typing.Union
> ???
E TypeError: issubclass() arg 1 must be a class
<frozen abc>:123: TypeError
=============================== warnings summary ===============================
../../../../../../../Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45
/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45: DeprecationWarning: The anyio.abc.BlockingPortal alias is deprecated, use anyio.from_thread.BlockingPortal instead.
_PortalFactoryType = Callable[[], AbstractContextManager[anyio.abc.BlockingPortal]]
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 7 passed, 1 skipped, 1 warning in 0.70s