mirror of
https://github.com/fastapi/fastapi.git
synced 2026-05-25 00:37:44 -04:00
➖ Drop support for Pydantic v1, keeping short temporary support for Pydantic v2's pydantic.v1 (#14575)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
5c7dceb80f
commit
e2cd8a4201
@@ -8,11 +8,11 @@ from pathlib import PurePath, PurePosixPath, PureWindowsPath
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from fastapi._compat import PYDANTIC_V2, Undefined
|
||||
from fastapi._compat import Undefined
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from pydantic import BaseModel, Field, ValidationError
|
||||
|
||||
from .utils import needs_pydanticv1, needs_pydanticv2
|
||||
from .utils import needs_pydanticv1
|
||||
|
||||
|
||||
class Person:
|
||||
@@ -59,12 +59,7 @@ class RoleEnum(Enum):
|
||||
class ModelWithConfig(BaseModel):
|
||||
role: Optional[RoleEnum] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"use_enum_values": True}
|
||||
else:
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
||||
model_config = {"use_enum_values": True}
|
||||
|
||||
|
||||
class ModelWithAlias(BaseModel):
|
||||
@@ -89,6 +84,18 @@ def test_encode_dict():
|
||||
}
|
||||
|
||||
|
||||
def test_encode_dict_include_exclude_list():
|
||||
pet = {"name": "Firulais", "owner": {"name": "Foo"}}
|
||||
assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}}
|
||||
assert jsonable_encoder(pet, include=["name"]) == {"name": "Firulais"}
|
||||
assert jsonable_encoder(pet, exclude=["owner"]) == {"name": "Firulais"}
|
||||
assert jsonable_encoder(pet, include=[]) == {}
|
||||
assert jsonable_encoder(pet, exclude=[]) == {
|
||||
"name": "Firulais",
|
||||
"owner": {"name": "Foo"},
|
||||
}
|
||||
|
||||
|
||||
def test_encode_class():
|
||||
person = Person(name="Foo")
|
||||
pet = Pet(owner=person, name="Firulais")
|
||||
@@ -130,7 +137,6 @@ def test_encode_unsupported():
|
||||
jsonable_encoder(unserializable)
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_encode_custom_json_encoders_model_pydanticv2():
|
||||
from pydantic import field_serializer
|
||||
|
||||
@@ -153,7 +159,9 @@ def test_encode_custom_json_encoders_model_pydanticv2():
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
@needs_pydanticv1
|
||||
def test_encode_custom_json_encoders_model_pydanticv1():
|
||||
class ModelWithCustomEncoder(BaseModel):
|
||||
from pydantic import v1
|
||||
|
||||
class ModelWithCustomEncoder(v1.BaseModel):
|
||||
dt_field: datetime
|
||||
|
||||
class Config:
|
||||
@@ -208,10 +216,12 @@ def test_encode_model_with_default():
|
||||
|
||||
@needs_pydanticv1
|
||||
def test_custom_encoders():
|
||||
from pydantic import v1
|
||||
|
||||
class safe_datetime(datetime):
|
||||
pass
|
||||
|
||||
class MyModel(BaseModel):
|
||||
class MyModel(v1.BaseModel):
|
||||
dt_field: safe_datetime
|
||||
|
||||
instance = MyModel(dt_field=safe_datetime.now())
|
||||
@@ -244,12 +254,7 @@ def test_encode_model_with_pure_path():
|
||||
class ModelWithPath(BaseModel):
|
||||
path: PurePath
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
else:
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
|
||||
test_path = PurePath("/foo", "bar")
|
||||
obj = ModelWithPath(path=test_path)
|
||||
@@ -260,12 +265,7 @@ def test_encode_model_with_pure_posix_path():
|
||||
class ModelWithPath(BaseModel):
|
||||
path: PurePosixPath
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
else:
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
|
||||
obj = ModelWithPath(path=PurePosixPath("/foo", "bar"))
|
||||
assert jsonable_encoder(obj) == {"path": "/foo/bar"}
|
||||
@@ -275,45 +275,44 @@ def test_encode_model_with_pure_windows_path():
|
||||
class ModelWithPath(BaseModel):
|
||||
path: PureWindowsPath
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
else:
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
|
||||
obj = ModelWithPath(path=PureWindowsPath("/foo", "bar"))
|
||||
assert jsonable_encoder(obj) == {"path": "\\foo\\bar"}
|
||||
|
||||
|
||||
def test_encode_pure_path():
|
||||
test_path = PurePath("/foo", "bar")
|
||||
|
||||
assert jsonable_encoder({"path": test_path}) == {"path": str(test_path)}
|
||||
|
||||
|
||||
@needs_pydanticv1
|
||||
def test_encode_root():
|
||||
class ModelWithRoot(BaseModel):
|
||||
from pydantic import v1
|
||||
|
||||
class ModelWithRoot(v1.BaseModel):
|
||||
__root__: str
|
||||
|
||||
model = ModelWithRoot(__root__="Foo")
|
||||
assert jsonable_encoder(model) == "Foo"
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_float():
|
||||
data = {"value": Decimal(1.23)}
|
||||
assert jsonable_encoder(data) == {"value": 1.23}
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_int():
|
||||
data = {"value": Decimal(2)}
|
||||
assert jsonable_encoder(data) == {"value": 2}
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_nan():
|
||||
data = {"value": Decimal("NaN")}
|
||||
assert isnan(jsonable_encoder(data)["value"])
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_infinity():
|
||||
data = {"value": Decimal("Infinity")}
|
||||
assert isinf(jsonable_encoder(data)["value"])
|
||||
@@ -330,7 +329,6 @@ def test_encode_deque_encodes_child_models():
|
||||
assert jsonable_encoder(dq)[0]["test"] == "test"
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_encode_pydantic_undefined():
|
||||
data = {"value": Undefined}
|
||||
assert jsonable_encoder(data) == {"value": None}
|
||||
|
||||
Reference in New Issue
Block a user