|
|
|
@ -6,43 +6,26 @@ from typing import ( |
|
|
|
) |
|
|
|
|
|
|
|
from fastapi._compat import may_v1 |
|
|
|
from fastapi._compat.shared import PYDANTIC_V2, lenient_issubclass |
|
|
|
from fastapi._compat.shared import lenient_issubclass |
|
|
|
from fastapi.types import ModelNameMap |
|
|
|
from pydantic import BaseModel |
|
|
|
from typing_extensions import Literal |
|
|
|
|
|
|
|
from . import v2 |
|
|
|
from .model_field import ModelField |
|
|
|
|
|
|
|
if PYDANTIC_V2: |
|
|
|
from .v2 import BaseConfig as BaseConfig |
|
|
|
from .v2 import FieldInfo as FieldInfo |
|
|
|
from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError |
|
|
|
from .v2 import RequiredParam as RequiredParam |
|
|
|
from .v2 import Undefined as Undefined |
|
|
|
from .v2 import UndefinedType as UndefinedType |
|
|
|
from .v2 import Url as Url |
|
|
|
from .v2 import Validator as Validator |
|
|
|
from .v2 import evaluate_forwardref as evaluate_forwardref |
|
|
|
from .v2 import get_missing_field_error as get_missing_field_error |
|
|
|
from .v2 import ( |
|
|
|
with_info_plain_validator_function as with_info_plain_validator_function, |
|
|
|
) |
|
|
|
else: |
|
|
|
from .v1 import BaseConfig as BaseConfig # type: ignore[assignment] |
|
|
|
from .v1 import FieldInfo as FieldInfo |
|
|
|
from .v1 import ( # type: ignore[assignment] |
|
|
|
PydanticSchemaGenerationError as PydanticSchemaGenerationError, |
|
|
|
) |
|
|
|
from .v1 import RequiredParam as RequiredParam |
|
|
|
from .v1 import Undefined as Undefined |
|
|
|
from .v1 import UndefinedType as UndefinedType |
|
|
|
from .v1 import Url as Url # type: ignore[assignment] |
|
|
|
from .v1 import Validator as Validator |
|
|
|
from .v1 import evaluate_forwardref as evaluate_forwardref |
|
|
|
from .v1 import get_missing_field_error as get_missing_field_error |
|
|
|
from .v1 import ( # type: ignore[assignment] |
|
|
|
with_info_plain_validator_function as with_info_plain_validator_function, |
|
|
|
) |
|
|
|
from .v2 import BaseConfig as BaseConfig |
|
|
|
from .v2 import FieldInfo as FieldInfo |
|
|
|
from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError |
|
|
|
from .v2 import RequiredParam as RequiredParam |
|
|
|
from .v2 import Undefined as Undefined |
|
|
|
from .v2 import UndefinedType as UndefinedType |
|
|
|
from .v2 import Url as Url |
|
|
|
from .v2 import Validator as Validator |
|
|
|
from .v2 import evaluate_forwardref as evaluate_forwardref |
|
|
|
from .v2 import get_missing_field_error as get_missing_field_error |
|
|
|
from .v2 import ( |
|
|
|
with_info_plain_validator_function as with_info_plain_validator_function, |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@lru_cache |
|
|
|
@ -60,11 +43,8 @@ def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]: |
|
|
|
def _is_undefined(value: object) -> bool: |
|
|
|
if isinstance(value, may_v1.UndefinedType): |
|
|
|
return True |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return isinstance(value, v2.UndefinedType) |
|
|
|
return False |
|
|
|
return isinstance(value, v2.UndefinedType) |
|
|
|
|
|
|
|
|
|
|
|
def _get_model_config(model: BaseModel) -> Any: |
|
|
|
@ -72,10 +52,8 @@ def _get_model_config(model: BaseModel) -> Any: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1._get_model_config(model) |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2._get_model_config(model) |
|
|
|
return v2._get_model_config(model) |
|
|
|
|
|
|
|
|
|
|
|
def _model_dump( |
|
|
|
@ -85,20 +63,15 @@ def _model_dump( |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1._model_dump(model, mode=mode, **kwargs) |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2._model_dump(model, mode=mode, **kwargs) |
|
|
|
return v2._model_dump(model, mode=mode, **kwargs) |
|
|
|
|
|
|
|
|
|
|
|
def _is_error_wrapper(exc: Exception) -> bool: |
|
|
|
if isinstance(exc, may_v1.ErrorWrapper): |
|
|
|
return True |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return isinstance(exc, v2.ErrorWrapper) |
|
|
|
return False |
|
|
|
return isinstance(exc, v2.ErrorWrapper) |
|
|
|
|
|
|
|
|
|
|
|
def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: |
|
|
|
@ -106,11 +79,8 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.copy_field_info(field_info=field_info, annotation=annotation) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.copy_field_info(field_info=field_info, annotation=annotation) |
|
|
|
return v2.copy_field_info(field_info=field_info, annotation=annotation) |
|
|
|
|
|
|
|
|
|
|
|
def create_body_model( |
|
|
|
@ -120,11 +90,8 @@ def create_body_model( |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.create_body_model(fields=fields, model_name=model_name) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.create_body_model(fields=fields, model_name=model_name) # type: ignore[arg-type] |
|
|
|
return v2.create_body_model(fields=fields, model_name=model_name) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def get_annotation_from_field_info( |
|
|
|
@ -136,13 +103,10 @@ def get_annotation_from_field_info( |
|
|
|
return v1.get_annotation_from_field_info( |
|
|
|
annotation=annotation, field_info=field_info, field_name=field_name |
|
|
|
) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.get_annotation_from_field_info( |
|
|
|
annotation=annotation, field_info=field_info, field_name=field_name |
|
|
|
) |
|
|
|
return v2.get_annotation_from_field_info( |
|
|
|
annotation=annotation, field_info=field_info, field_name=field_name |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def is_bytes_field(field: ModelField) -> bool: |
|
|
|
@ -150,11 +114,8 @@ def is_bytes_field(field: ModelField) -> bool: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.is_bytes_field(field) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.is_bytes_field(field) # type: ignore[arg-type] |
|
|
|
return v2.is_bytes_field(field) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def is_bytes_sequence_field(field: ModelField) -> bool: |
|
|
|
@ -162,11 +123,8 @@ def is_bytes_sequence_field(field: ModelField) -> bool: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.is_bytes_sequence_field(field) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.is_bytes_sequence_field(field) # type: ignore[arg-type] |
|
|
|
return v2.is_bytes_sequence_field(field) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def is_scalar_field(field: ModelField) -> bool: |
|
|
|
@ -174,11 +132,8 @@ def is_scalar_field(field: ModelField) -> bool: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.is_scalar_field(field) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.is_scalar_field(field) # type: ignore[arg-type] |
|
|
|
return v2.is_scalar_field(field) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def is_scalar_sequence_field(field: ModelField) -> bool: |
|
|
|
@ -186,11 +141,8 @@ def is_scalar_sequence_field(field: ModelField) -> bool: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.is_scalar_sequence_field(field) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.is_scalar_sequence_field(field) # type: ignore[arg-type] |
|
|
|
return v2.is_scalar_sequence_field(field) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def is_sequence_field(field: ModelField) -> bool: |
|
|
|
@ -198,11 +150,8 @@ def is_sequence_field(field: ModelField) -> bool: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.is_sequence_field(field) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.is_sequence_field(field) # type: ignore[arg-type] |
|
|
|
return v2.is_sequence_field(field) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: |
|
|
|
@ -210,11 +159,8 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
return v1.serialize_sequence_value(field=field, value=value) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type] |
|
|
|
return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type] |
|
|
|
|
|
|
|
|
|
|
|
def _model_rebuild(model: type[BaseModel]) -> None: |
|
|
|
@ -222,9 +168,7 @@ def _model_rebuild(model: type[BaseModel]) -> None: |
|
|
|
from fastapi._compat import v1 |
|
|
|
|
|
|
|
v1._model_rebuild(model) |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
else: |
|
|
|
v2._model_rebuild(model) |
|
|
|
|
|
|
|
|
|
|
|
@ -241,22 +185,12 @@ def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap: |
|
|
|
all_flat_models = v1_flat_models |
|
|
|
else: |
|
|
|
all_flat_models = set() |
|
|
|
if PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
v2_model_fields = [ |
|
|
|
field for field in fields if isinstance(field, v2.ModelField) |
|
|
|
] |
|
|
|
v2_flat_models = v2.get_flat_models_from_fields( |
|
|
|
v2_model_fields, known_models=set() |
|
|
|
) |
|
|
|
all_flat_models = all_flat_models.union(v2_flat_models) |
|
|
|
|
|
|
|
model_name_map = v2.get_model_name_map(all_flat_models) |
|
|
|
return model_name_map |
|
|
|
from fastapi._compat import v1 |
|
|
|
v2_model_fields = [field for field in fields if isinstance(field, v2.ModelField)] |
|
|
|
v2_flat_models = v2.get_flat_models_from_fields(v2_model_fields, known_models=set()) |
|
|
|
all_flat_models = all_flat_models.union(v2_flat_models) |
|
|
|
|
|
|
|
model_name_map = v1.get_model_name_map(all_flat_models) |
|
|
|
model_name_map = v2.get_model_name_map(all_flat_models) |
|
|
|
return model_name_map |
|
|
|
|
|
|
|
|
|
|
|
@ -279,25 +213,19 @@ def get_definitions( |
|
|
|
model_name_map=model_name_map, |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
if not PYDANTIC_V2: |
|
|
|
return v1_field_maps, v1_definitions |
|
|
|
else: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)] |
|
|
|
v2_field_maps, v2_definitions = v2.get_definitions( |
|
|
|
fields=v2_fields, |
|
|
|
model_name_map=model_name_map, |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
all_definitions = {**v1_definitions, **v2_definitions} |
|
|
|
all_field_maps = {**v1_field_maps, **v2_field_maps} |
|
|
|
return all_field_maps, all_definitions |
|
|
|
|
|
|
|
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)] |
|
|
|
v2_field_maps, v2_definitions = v2.get_definitions( |
|
|
|
fields=v2_fields, |
|
|
|
model_name_map=model_name_map, |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
all_definitions = {**v1_definitions, **v2_definitions} |
|
|
|
all_field_maps = {**v1_field_maps, **v2_field_maps} |
|
|
|
return all_field_maps, all_definitions |
|
|
|
|
|
|
|
# Pydantic v1 is not supported since Python 3.14 |
|
|
|
else: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)] |
|
|
|
v2_field_maps, v2_definitions = v2.get_definitions( |
|
|
|
fields=v2_fields, |
|
|
|
@ -326,33 +254,24 @@ def get_schema_from_model_field( |
|
|
|
field_mapping=field_mapping, |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
else: |
|
|
|
assert PYDANTIC_V2 |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return v2.get_schema_from_model_field( |
|
|
|
field=field, # type: ignore[arg-type] |
|
|
|
model_name_map=model_name_map, |
|
|
|
field_mapping=field_mapping, # type: ignore[arg-type] |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
return v2.get_schema_from_model_field( |
|
|
|
field=field, # type: ignore[arg-type] |
|
|
|
model_name_map=model_name_map, |
|
|
|
field_mapping=field_mapping, # type: ignore[arg-type] |
|
|
|
separate_input_output_schemas=separate_input_output_schemas, |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def _is_model_field(value: Any) -> bool: |
|
|
|
if isinstance(value, may_v1.ModelField): |
|
|
|
return True |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return isinstance(value, v2.ModelField) |
|
|
|
return False |
|
|
|
return isinstance(value, v2.ModelField) |
|
|
|
|
|
|
|
|
|
|
|
def _is_model_class(value: Any) -> bool: |
|
|
|
if lenient_issubclass(value, may_v1.BaseModel): |
|
|
|
return True |
|
|
|
elif PYDANTIC_V2: |
|
|
|
from . import v2 |
|
|
|
|
|
|
|
return lenient_issubclass(value, v2.BaseModel) # type: ignore[attr-defined] |
|
|
|
return False |
|
|
|
return lenient_issubclass(value, v2.BaseModel) # type: ignore[attr-defined] |
|
|
|
|