From 00e080ab4278785786507b67214fcee54327ca21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 4 Jul 2023 14:29:11 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20new=20Pydantic=20Field=20para?= =?UTF-8?q?m=20options=20to=20Query,=20Cookie,=20Body,=20etc.=20(#9797)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/param_functions.py | 198 +++++++++++++++++++++++++-- fastapi/params.py | 271 +++++++++++++++++++++++++++++++++---- 2 files changed, 435 insertions(+), 34 deletions(-) diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 5efd8b995..a43afaf31 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -1,14 +1,22 @@ -from typing import Any, Callable, List, Optional, Sequence +from typing import Any, Callable, Dict, List, Optional, Sequence, Union from fastapi import params from fastapi._compat import Undefined from typing_extensions import Annotated, deprecated +_Unset: Any = Undefined + def Path( # noqa: N802 default: Any = ..., *, + default_factory: Union[Callable[[], Any], None] = _Unset, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -24,6 +32,12 @@ def Path( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -31,14 +45,19 @@ def Path( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Path( default=default, + default_factory=default_factory, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -49,10 +68,17 @@ def Path( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -60,7 +86,13 @@ def Path( # noqa: N802 def Query( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -76,6 +108,12 @@ def Query( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -83,14 +121,19 @@ def Query( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Query( default=default, + default_factory=default_factory, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -101,10 +144,17 @@ def Query( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -112,7 +162,13 @@ def Query( # noqa: N802 def Header( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, convert_underscores: bool = True, title: Optional[str] = None, description: Optional[str] = None, @@ -129,6 +185,12 @@ def Header( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -136,14 +198,19 @@ def Header( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Header( default=default, + default_factory=default_factory, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, convert_underscores=convert_underscores, title=title, description=description, @@ -155,10 +222,17 @@ def Header( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -166,7 +240,13 @@ def Header( # noqa: N802 def Cookie( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -182,6 +262,12 @@ def Cookie( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -189,14 +275,19 @@ def Cookie( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Cookie( default=default, + default_factory=default_factory, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -207,10 +298,17 @@ def Cookie( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, deprecated=deprecated, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -218,9 +316,15 @@ def Cookie( # noqa: N802 def Body( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, embed: bool = False, media_type: str = "application/json", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -236,6 +340,12 @@ def Body( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -243,14 +353,21 @@ def Body( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Body( default=default, + default_factory=default_factory, embed=embed, media_type=media_type, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -261,8 +378,17 @@ def Body( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -270,8 +396,14 @@ def Body( # noqa: N802 def Form( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, media_type: str = "application/x-www-form-urlencoded", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -287,6 +419,12 @@ def Form( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -294,13 +432,20 @@ def Form( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.Form( default=default, + default_factory=default_factory, media_type=media_type, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -311,8 +456,17 @@ def Form( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -320,8 +474,14 @@ def Form( # noqa: N802 def File( # noqa: N802 default: Any = Undefined, *, + default_factory: Union[Callable[[], Any], None] = _Unset, media_type: str = "multipart/form-data", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -337,6 +497,12 @@ def File( # noqa: N802 "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -344,13 +510,20 @@ def File( # noqa: N802 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ) -> Any: return params.File( default=default, + default_factory=default_factory, media_type=media_type, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -361,8 +534,17 @@ def File( # noqa: N802 max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, example=example, examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) diff --git a/fastapi/params.py b/fastapi/params.py index 53d30cc33..30af5713e 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -1,12 +1,14 @@ import warnings from enum import Enum -from typing import Any, Callable, List, Optional, Sequence, Type +from typing import Any, Callable, Dict, List, Optional, Sequence, Union from pydantic.fields import FieldInfo from typing_extensions import Annotated, deprecated from ._compat import PYDANTIC_V2, Undefined +_Unset: Any = Undefined + class ParamTypes(Enum): query = "query" @@ -22,8 +24,14 @@ class Param(FieldInfo): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -39,6 +47,12 @@ class Param(FieldInfo): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -46,13 +60,14 @@ class Param(FieldInfo): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): self.deprecated = deprecated - if example is not Undefined: + if example is not _Unset: warnings.warn( "`example` has been depreacated, please use `examples` instead", category=DeprecationWarning, @@ -62,6 +77,7 @@ class Param(FieldInfo): self.include_in_schema = include_in_schema kwargs = dict( default=default, + default_factory=default_factory, alias=alias, title=title, description=description, @@ -71,24 +87,40 @@ class Param(FieldInfo): le=le, min_length=min_length, max_length=max_length, + discriminator=discriminator, + multiple_of=multiple_of, + allow_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, **extra, ) if examples is not None: kwargs["examples"] = examples if regex is not None: - print(f"regex: {regex}") warnings.warn( "`regex` has been depreacated, please use `pattern` instead", category=DeprecationWarning, stacklevel=4, ) + current_json_schema_extra = json_schema_extra or extra if PYDANTIC_V2: - kwargs["annotation"] = annotation + kwargs.update( + { + "annotation": annotation, + "alias_priority": alias_priority, + "validation_alias": validation_alias, + "serialization_alias": serialization_alias, + "strict": strict, + "json_schema_extra": current_json_schema_extra, + } + ) kwargs["pattern"] = pattern or regex else: kwargs["regex"] = pattern or regex + kwargs.update(**current_json_schema_extra) + use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} - super().__init__(**kwargs) + super().__init__(**use_kwargs) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.default})" @@ -101,8 +133,14 @@ class Path(Param): self, default: Any = ..., *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -118,6 +156,12 @@ class Path(Param): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -125,17 +169,22 @@ class Path(Param): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): assert default is ..., "Path parameters cannot have a default value" self.in_ = self.in_ super().__init__( default=default, + default_factory=default_factory, annotation=annotation, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -146,10 +195,17 @@ class Path(Param): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, deprecated=deprecated, example=example, examples=examples, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -161,8 +217,14 @@ class Query(Param): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -178,6 +240,12 @@ class Query(Param): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -185,15 +253,20 @@ class Query(Param): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): super().__init__( default=default, + default_factory=default_factory, annotation=annotation, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -204,10 +277,17 @@ class Query(Param): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, deprecated=deprecated, example=example, examples=examples, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -219,8 +299,14 @@ class Header(Param): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, convert_underscores: bool = True, title: Optional[str] = None, description: Optional[str] = None, @@ -237,6 +323,12 @@ class Header(Param): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -244,16 +336,21 @@ class Header(Param): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): self.convert_underscores = convert_underscores super().__init__( default=default, + default_factory=default_factory, annotation=annotation, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -264,10 +361,17 @@ class Header(Param): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, deprecated=deprecated, example=example, examples=examples, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -279,8 +383,14 @@ class Cookie(Param): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -296,6 +406,12 @@ class Cookie(Param): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -303,15 +419,20 @@ class Cookie(Param): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, deprecated: Optional[bool] = None, include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): super().__init__( default=default, + default_factory=default_factory, annotation=annotation, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -322,10 +443,17 @@ class Cookie(Param): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, deprecated=deprecated, example=example, examples=examples, include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -335,10 +463,16 @@ class Body(FieldInfo): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, embed: bool = False, media_type: str = "application/json", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -354,6 +488,12 @@ class Body(FieldInfo): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -361,20 +501,26 @@ class Body(FieldInfo): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): self.embed = embed self.media_type = media_type - if example is not Undefined: + self.deprecated = deprecated + if example is not _Unset: warnings.warn( "`example` has been depreacated, please use `examples` instead", category=DeprecationWarning, stacklevel=4, ) self.example = example + self.include_in_schema = include_in_schema kwargs = dict( default=default, + default_factory=default_factory, alias=alias, title=title, description=description, @@ -384,6 +530,11 @@ class Body(FieldInfo): le=le, min_length=min_length, max_length=max_length, + discriminator=discriminator, + multiple_of=multiple_of, + allow_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, **extra, ) if examples is not None: @@ -394,14 +545,26 @@ class Body(FieldInfo): category=DeprecationWarning, stacklevel=4, ) + current_json_schema_extra = json_schema_extra or extra if PYDANTIC_V2: - kwargs["annotation"] = annotation + kwargs.update( + { + "annotation": annotation, + "alias_priority": alias_priority, + "validation_alias": validation_alias, + "serialization_alias": serialization_alias, + "strict": strict, + "json_schema_extra": current_json_schema_extra, + } + ) kwargs["pattern"] = pattern or regex else: kwargs["regex"] = pattern or regex - super().__init__( - **kwargs, - ) + kwargs.update(**current_json_schema_extra) + + use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} + + super().__init__(**use_kwargs) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.default})" @@ -412,9 +575,15 @@ class Form(Body): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, media_type: str = "application/x-www-form-urlencoded", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -430,6 +599,12 @@ class Form(Body): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -437,15 +612,22 @@ class Form(Body): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): super().__init__( default=default, + default_factory=default_factory, annotation=annotation, embed=True, media_type=media_type, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -456,8 +638,17 @@ class Form(Body): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, example=example, examples=examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, ) @@ -467,9 +658,15 @@ class File(Form): self, default: Any = Undefined, *, - annotation: Optional[Type[Any]] = None, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, media_type: str = "multipart/form-data", alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, title: Optional[str] = None, description: Optional[str] = None, gt: Optional[float] = None, @@ -485,6 +682,12 @@ class File(Form): "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, examples: Optional[List[Any]] = None, example: Annotated[ Optional[Any], @@ -492,14 +695,21 @@ class File(Form): "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), - ] = Undefined, + ] = _Unset, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, **extra: Any, ): super().__init__( default=default, + default_factory=default_factory, annotation=annotation, media_type=media_type, alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, title=title, description=description, gt=gt, @@ -510,8 +720,17 @@ class File(Form): max_length=max_length, pattern=pattern, regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, example=example, examples=examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, **extra, )