Browse Source

🐛 Remove `Required` shadowing from fastapi using Pydantic v2 (#12197)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sofie Van Landeghem <[email protected]>
pull/12431/head
José Pacheco 6 months ago
committed by GitHub
parent
commit
8ae4603d68
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      docs_src/query_params_str_validations/tutorial006d.py
  2. 3
      docs_src/query_params_str_validations/tutorial006d_an.py
  3. 3
      docs_src/query_params_str_validations/tutorial006d_an_py39.py
  4. 9
      fastapi/_compat.py
  5. 14
      fastapi/dependencies/utils.py

3
docs_src/query_params_str_validations/tutorial006d.py

@ -1,11 +1,10 @@
from fastapi import FastAPI, Query
from pydantic import Required
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(default=Required, min_length=3)):
async def read_items(q: str = Query(default=..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})

3
docs_src/query_params_str_validations/tutorial006d_an.py

@ -1,12 +1,11 @@
from fastapi import FastAPI, Query
from pydantic import Required
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = Required):
async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})

3
docs_src/query_params_str_validations/tutorial006d_an_py39.py

@ -1,13 +1,12 @@
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import Required
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = Required):
async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})

9
fastapi/_compat.py

@ -71,7 +71,7 @@ if PYDANTIC_V2:
general_plain_validator_function as with_info_plain_validator_function, # noqa: F401
)
Required = PydanticUndefined
RequiredParam = PydanticUndefined
Undefined = PydanticUndefined
UndefinedType = PydanticUndefinedType
evaluate_forwardref = eval_type_lenient
@ -313,9 +313,10 @@ else:
from pydantic.fields import ( # type: ignore[no-redef,attr-defined]
ModelField as ModelField, # noqa: F401
)
from pydantic.fields import ( # type: ignore[no-redef,attr-defined]
Required as Required, # noqa: F401
)
# Keeping old "Required" functionality from Pydantic V1, without
# shadowing typing.Required.
RequiredParam: Any = Ellipsis # type: ignore[no-redef]
from pydantic.fields import ( # type: ignore[no-redef,attr-defined]
Undefined as Undefined,
)

14
fastapi/dependencies/utils.py

@ -24,7 +24,7 @@ from fastapi._compat import (
PYDANTIC_V2,
ErrorWrapper,
ModelField,
Required,
RequiredParam,
Undefined,
_regenerate_error_with_loc,
copy_field_info,
@ -377,7 +377,9 @@ def analyze_param(
field_info = copy_field_info(
field_info=fastapi_annotation, annotation=use_annotation
)
assert field_info.default is Undefined or field_info.default is Required, (
assert (
field_info.default is Undefined or field_info.default is RequiredParam
), (
f"`{field_info.__class__.__name__}` default value cannot be set in"
f" `Annotated` for {param_name!r}. Set the default value with `=` instead."
)
@ -385,7 +387,7 @@ def analyze_param(
assert not is_path_param, "Path parameters cannot have default values"
field_info.default = value
else:
field_info.default = Required
field_info.default = RequiredParam
# Get Annotated Depends
elif isinstance(fastapi_annotation, params.Depends):
depends = fastapi_annotation
@ -434,9 +436,9 @@ def analyze_param(
), f"Cannot specify FastAPI annotation for type {type_annotation!r}"
# Handle default assignations, neither field_info nor depends was not found in Annotated nor default value
elif field_info is None and depends is None:
default_value = value if value is not inspect.Signature.empty else Required
default_value = value if value is not inspect.Signature.empty else RequiredParam
if is_path_param:
# We might check here that `default_value is Required`, but the fact is that the same
# We might check here that `default_value is RequiredParam`, but the fact is that the same
# parameter might sometimes be a path parameter and sometimes not. See
# `tests/test_infer_param_optionality.py` for an example.
field_info = params.Path(annotation=use_annotation)
@ -480,7 +482,7 @@ def analyze_param(
type_=use_annotation_from_field_info,
default=field_info.default,
alias=alias,
required=field_info.default in (Required, Undefined),
required=field_info.default in (RequiredParam, Undefined),
field_info=field_info,
)
if is_path_param:

Loading…
Cancel
Save