Browse Source
🐛 Fix optional sequence handling with new union syntax from Python 3.10 (#14430)
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 <[email protected]>
pull/10647/merge
Victorien
7 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with
16 additions and
3 deletions
-
fastapi/_compat/v2.py
-
tests/test_compat.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): |
|
|
|
|
|
|
|
@ -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.""" |
|
|
|
|