From 80d69ae0bb393c728c61c41086b770237b7b676c Mon Sep 17 00:00:00 2001 From: Victorien <65306057+Viicos@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:59:38 +0100 Subject: [PATCH] =?utf8?q?=F0=9F=90=9B=20Fix=20optional=20sequence=20handl?= =?utf8?q?ing=20with=20new=20union=20syntax=20from=20Python=203.10=20(#144?= =?utf8?q?30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- fastapi/_compat/v2.py | 4 ++-- tests/test_compat.py | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 543a42dda0..0faa7d5a8d 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -17,7 +17,7 @@ from typing import ( from fastapi._compat import may_v1, shared from fastapi.openapi.constants import REF_TEMPLATE -from fastapi.types import IncEx, ModelNameMap +from fastapi.types import IncEx, ModelNameMap, UnionType from pydantic import BaseModel, TypeAdapter, create_model from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation @@ -381,7 +381,7 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: origin_type = get_origin(field.field_info.annotation) or field.field_info.annotation - if origin_type is Union: # Handle optional sequences + if origin_type is Union or origin_type is UnionType: # Handle optional sequences union_args = get_args(field.field_info.annotation) for union_arg in union_args: if union_arg is type(None): diff --git a/tests/test_compat.py b/tests/test_compat.py index c3a97209a9..26537c5ab7 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -14,7 +14,7 @@ from fastapi.testclient import TestClient from pydantic import BaseModel, ConfigDict from pydantic.fields import FieldInfo -from .utils import needs_py_lt_314, needs_pydanticv2 +from .utils import needs_py310, needs_py_lt_314, needs_pydanticv2 @needs_pydanticv2 @@ -148,6 +148,19 @@ def test_serialize_sequence_value_with_optional_list(): assert isinstance(result, list) +@needs_pydanticv2 +@needs_py310 +def test_serialize_sequence_value_with_optional_list_pipe_union(): + """Test that serialize_sequence_value handles optional lists correctly (with new syntax).""" + from fastapi._compat import v2 + + field_info = FieldInfo(annotation=list[str] | None) + field = v2.ModelField(name="items", field_info=field_info) + result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"]) + assert result == ["a", "b", "c"] + assert isinstance(result, list) + + @needs_pydanticv2 def test_serialize_sequence_value_with_none_first_in_union(): """Test that serialize_sequence_value handles Union[None, List[...]] correctly.""" -- 2.47.3