persuing 'on_error="omit"'

This commit is contained in:
JONEMI21 2025-11-07 15:02:37 +00:00
parent 1e22422ff9
commit d90b39a60a
5 changed files with 2 additions and 50 deletions

View File

@ -28,7 +28,6 @@ if PYDANTIC_V2:
from .v2 import Validator as Validator from .v2 import Validator as Validator
from .v2 import evaluate_forwardref as evaluate_forwardref from .v2 import evaluate_forwardref as evaluate_forwardref
from .v2 import get_missing_field_error as get_missing_field_error from .v2 import get_missing_field_error as get_missing_field_error
from .v2 import ignore_invalid as ignore_invalid
from .v2 import ( from .v2 import (
with_info_plain_validator_function as with_info_plain_validator_function, with_info_plain_validator_function as with_info_plain_validator_function,
) )
@ -45,7 +44,6 @@ else:
from .v1 import Validator as Validator from .v1 import Validator as Validator
from .v1 import evaluate_forwardref as evaluate_forwardref from .v1 import evaluate_forwardref as evaluate_forwardref
from .v1 import get_missing_field_error as get_missing_field_error from .v1 import get_missing_field_error as get_missing_field_error
from .v1 import ignore_invalid as ignore_invalid
from .v1 import ( # type: ignore[assignment] from .v1 import ( # type: ignore[assignment]
with_info_plain_validator_function as with_info_plain_validator_function, with_info_plain_validator_function as with_info_plain_validator_function,
) )

View File

@ -252,30 +252,3 @@ def annotation_is_pydantic_v1(annotation: Any) -> bool:
if annotation_is_pydantic_v1(sub_annotation): if annotation_is_pydantic_v1(sub_annotation):
return True return True
return False return False
def remove_invalid(v: Any, handler: Callable[[Any], Any]) -> Any:
try:
return handler(v)
except ValidationError as exc:
if not isinstance(v, dict):
raise exc
# remove invalid values from invalid keys and revalidate
errors = may_v1._regenerate_error_with_loc(errors=[exc.errors()], loc_prefix=())
for err in errors:
loc = err.get("loc", ())
if len(loc) == 1:
v.pop(loc[0], None)
elif len(loc) == 2 and isinstance(v.get(loc[0]), list):
try:
v[loc[0]][loc[1]] = None
except (ValueError, IndexError):
pass
# remove the None values from lists
for key in list(v.keys()):
if isinstance(v[key], list):
v[key] = [item for item in v[key] if item is not None]
# remove empty lists
if v[key] == []:
v.pop(key)
return handler(v)

View File

@ -349,6 +349,3 @@ def create_body_model(
def get_model_fields(model: Type[BaseModel]) -> List[ModelField]: def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
return list(model.__fields__.values()) # type: ignore[attr-defined] return list(model.__fields__.values()) # type: ignore[attr-defined]
def ignore_invalid(field_info: FieldInfo) -> FieldInfo:
return field_info

View File

@ -488,10 +488,3 @@ def get_flat_models_from_fields(
def get_long_model_name(model: TypeModelOrEnum) -> str: def get_long_model_name(model: TypeModelOrEnum) -> str:
return f"{model.__module__}__{model.__qualname__}".replace(".", "__") return f"{model.__module__}__{model.__qualname__}".replace(".", "__")
def ignore_invalid(field_info: FieldInfo) -> FieldInfo:
new_field_info = copy(field_info)
new_field_info.metadata = getattr(field_info, "metadata", []) + [
WrapValidator(shared.remove_invalid)
]
return new_field_info

View File

@ -34,7 +34,6 @@ from fastapi._compat import (
get_annotation_from_field_info, get_annotation_from_field_info,
get_cached_model_fields, get_cached_model_fields,
get_missing_field_error, get_missing_field_error,
ignore_invalid,
is_bytes_field, is_bytes_field,
is_bytes_sequence_field, is_bytes_sequence_field,
is_scalar_field, is_scalar_field,
@ -64,7 +63,7 @@ from fastapi.security.oauth2 import OAuth2, SecurityScopes
from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.security.open_id_connect_url import OpenIdConnect
from fastapi.types import DependencyCacheKey from fastapi.types import DependencyCacheKey
from fastapi.utils import create_model_field, get_path_param_names from fastapi.utils import create_model_field, get_path_param_names
from pydantic import BaseModel from pydantic import BaseModel, TypeAdapter
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from starlette.background import BackgroundTasks as StarletteBackgroundTasks from starlette.background import BackgroundTasks as StarletteBackgroundTasks
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
@ -527,15 +526,7 @@ def analyze_param(
if is_scalar_sequence_field(field) or is_scalar_sequence_mapping_field( if is_scalar_sequence_field(field) or is_scalar_sequence_mapping_field(
field field
): ):
field = create_model_field( field._type_adapter.core_schema["on_error"] = "omit"
name=param_name,
type_=use_annotation_from_field_info,
default=field_info.default,
alias=alias,
required=field_info.default
in (RequiredParam, may_v1.RequiredParam, Undefined),
field_info=ignore_invalid(field_info),
)
return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) return ParamDetails(type_annotation=type_annotation, depends=depends, field=field)