]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
✨ Add support for not needing `...` as default value in required Query(), Path()...
authorSebastián Ramírez <tiangolo@gmail.com>
Fri, 13 May 2022 23:38:22 +0000 (18:38 -0500)
committerGitHub <noreply@github.com>
Fri, 13 May 2022 23:38:22 +0000 (18:38 -0500)
* ✨ Do not require default value in Query(), Path(), Header(), etc

* 📝 Update source examples for docs with default and required values

* ✅ Update tests with new default values and not required Ellipsis

* 📝 Update docs for Query params and update info about default value, required, Ellipsis

107 files changed:
docs/en/docs/tutorial/query-params-str-validations.md
docs_src/additional_status_codes/tutorial001.py
docs_src/app_testing/app_b/main.py
docs_src/app_testing/app_b_py310/main.py
docs_src/bigger_applications/app/dependencies.py
docs_src/body_fields/tutorial001.py
docs_src/body_fields/tutorial001_py310.py
docs_src/body_multiple_params/tutorial001.py
docs_src/body_multiple_params/tutorial001_py310.py
docs_src/body_multiple_params/tutorial003.py
docs_src/body_multiple_params/tutorial003_py310.py
docs_src/body_multiple_params/tutorial004.py
docs_src/body_multiple_params/tutorial004_py310.py
docs_src/body_multiple_params/tutorial005.py
docs_src/body_multiple_params/tutorial005_py310.py
docs_src/cookie_params/tutorial001.py
docs_src/cookie_params/tutorial001_py310.py
docs_src/custom_request_and_route/tutorial001.py
docs_src/custom_request_and_route/tutorial002.py
docs_src/dependencies/tutorial005.py
docs_src/dependencies/tutorial005_py310.py
docs_src/dependencies/tutorial006.py
docs_src/dependencies/tutorial012.py
docs_src/extra_data_types/tutorial001.py
docs_src/extra_data_types/tutorial001_py310.py
docs_src/header_params/tutorial001.py
docs_src/header_params/tutorial001_py310.py
docs_src/header_params/tutorial002.py
docs_src/header_params/tutorial002_py310.py
docs_src/header_params/tutorial003.py
docs_src/header_params/tutorial003_py310.py
docs_src/header_params/tutorial003_py39.py
docs_src/path_params_numeric_validations/tutorial001.py
docs_src/path_params_numeric_validations/tutorial001_py310.py
docs_src/path_params_numeric_validations/tutorial002.py
docs_src/path_params_numeric_validations/tutorial003.py
docs_src/path_params_numeric_validations/tutorial004.py
docs_src/path_params_numeric_validations/tutorial005.py
docs_src/path_params_numeric_validations/tutorial006.py
docs_src/query_params_str_validations/tutorial002.py
docs_src/query_params_str_validations/tutorial002_py310.py
docs_src/query_params_str_validations/tutorial003.py
docs_src/query_params_str_validations/tutorial003_py310.py
docs_src/query_params_str_validations/tutorial004.py
docs_src/query_params_str_validations/tutorial004_py310.py
docs_src/query_params_str_validations/tutorial005.py
docs_src/query_params_str_validations/tutorial006.py
docs_src/query_params_str_validations/tutorial006b.py [new file with mode: 0644]
docs_src/query_params_str_validations/tutorial006c.py [new file with mode: 0644]
docs_src/query_params_str_validations/tutorial006c_py310.py [new file with mode: 0644]
docs_src/query_params_str_validations/tutorial006d.py [new file with mode: 0644]
docs_src/query_params_str_validations/tutorial007.py
docs_src/query_params_str_validations/tutorial007_py310.py
docs_src/query_params_str_validations/tutorial008.py
docs_src/query_params_str_validations/tutorial008_py310.py
docs_src/query_params_str_validations/tutorial009.py
docs_src/query_params_str_validations/tutorial009_py310.py
docs_src/query_params_str_validations/tutorial010.py
docs_src/query_params_str_validations/tutorial010_py310.py
docs_src/query_params_str_validations/tutorial011.py
docs_src/query_params_str_validations/tutorial011_py310.py
docs_src/query_params_str_validations/tutorial011_py39.py
docs_src/query_params_str_validations/tutorial012.py
docs_src/query_params_str_validations/tutorial012_py39.py
docs_src/query_params_str_validations/tutorial013.py
docs_src/query_params_str_validations/tutorial014.py
docs_src/query_params_str_validations/tutorial014_py310.py
docs_src/request_files/tutorial001.py
docs_src/request_files/tutorial001_02.py
docs_src/request_files/tutorial001_02_py310.py
docs_src/request_files/tutorial001_03.py
docs_src/request_files/tutorial002.py
docs_src/request_files/tutorial002_py39.py
docs_src/request_files/tutorial003.py
docs_src/request_files/tutorial003_py39.py
docs_src/request_forms/tutorial001.py
docs_src/request_forms_and_files/tutorial001.py
docs_src/schema_extra_example/tutorial002.py
docs_src/schema_extra_example/tutorial002_py310.py
docs_src/schema_extra_example/tutorial003.py
docs_src/schema_extra_example/tutorial003_py310.py
docs_src/schema_extra_example/tutorial004.py
docs_src/schema_extra_example/tutorial004_py310.py
docs_src/websockets/tutorial002.py
fastapi/dependencies/utils.py
fastapi/openapi/models.py
fastapi/param_functions.py
fastapi/params.py
fastapi/security/oauth2.py
fastapi/utils.py
tests/main.py
tests/test_dependency_normal_exceptions.py
tests/test_forms_from_non_typing_sequences.py
tests/test_invalid_sequence_param.py
tests/test_jsonable_encoder.py
tests/test_modules_same_name_body/app/a.py
tests/test_modules_same_name_body/app/b.py
tests/test_multi_query_errors.py
tests/test_multipart_installation.py
tests/test_param_class.py
tests/test_param_include_in_schema.py
tests/test_repeated_dependency_schema.py
tests/test_request_body_parameters_media_type.py
tests/test_schema_extra_examples.py
tests/test_serialize_response_model.py
tests/test_starlette_urlconvertors.py
tests/test_tuples.py

index ee62b97181028e6cfdab3cc78b6f9ec8d458ae6d..c5fc35b88aefff763d313a01caf58a972ab30fd3 100644 (file)
@@ -16,12 +16,12 @@ Let's take this application as example:
     {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
     ```
 
-The query parameter `q` is of type `Optional[str]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
+The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
 
 !!! note
     FastAPI will know that the value of `q` is not required because of the default value `= None`.
 
-    The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
+    The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors.
 
 ## Additional validation
 
@@ -59,24 +59,24 @@ And now use it as the default value of your parameter, setting the parameter `ma
     {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
     ```
 
-As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value.
+As we have to replace the default value `None` in the function with `Query()`, we can now set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value.
 
 So:
 
 ```Python
-q: Optional[str] = Query(None)
+q: Union[str, None] = Query(default=None)
 ```
 
 ...makes the parameter optional, the same as:
 
 ```Python
-q: Optional[str] = None
+q: Union[str, None] = None
 ```
 
 And in Python 3.10 and above:
 
 ```Python
-q: str | None = Query(None)
+q: str | None = Query(default=None)
 ```
 
 ...makes the parameter optional, the same as:
@@ -97,17 +97,17 @@ But it declares it explicitly as being a query parameter.
     or the:
 
     ```Python
-    = Query(None)
+    = Query(default=None)
     ```
 
     as it will use that `None` as the default value, and that way make the parameter **not required**.
 
-    The `Optional` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
+    The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
 
 Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
 
 ```Python
-q: str = Query(None, max_length=50)
+q: Union[str, None] = Query(default=None, max_length=50)
 ```
 
 This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
@@ -118,7 +118,7 @@ You can also add a parameter `min_length`:
 
 === "Python 3.6 and above"
 
-    ```Python hl_lines="9"
+    ```Python hl_lines="10"
     {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
     ```
 
@@ -134,13 +134,13 @@ You can define a <abbr title="A regular expression, regex or regexp is a sequenc
 
 === "Python 3.6 and above"
 
-    ```Python hl_lines="10"
+    ```Python hl_lines="11"
     {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
     ```
 
 === "Python 3.10 and above"
 
-    ```Python hl_lines="8"
+    ```Python hl_lines="9"
     {!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
     ```
 
@@ -156,7 +156,7 @@ But whenever you need them and go and learn them, know that you can already use
 
 ## Default values
 
-The same way that you can pass `None` as the first argument to be used as the default value, you can pass other values.
+The same way that you can pass `None` as the value for the `default` parameter, you can pass other values.
 
 Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
 
@@ -178,26 +178,68 @@ q: str
 instead of:
 
 ```Python
-q: Optional[str] = None
+q: Union[str, None] = None
 ```
 
 But we are now declaring it with `Query`, for example like:
 
 ```Python
-q: Optional[str] = Query(None, min_length=3)
+q: Union[str, None] = Query(default=None, min_length=3)
 ```
 
-So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument:
+So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
 
 ```Python hl_lines="7"
 {!../../../docs_src/query_params_str_validations/tutorial006.py!}
 ```
 
+### Required with Ellipsis (`...`)
+
+There's an alternative way to explicitly declare that a value is required. You can set the `default` parameter to the literal value `...`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
+```
+
 !!! info
     If you hadn't seen that `...` before: it is a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
 
+    It is used by Pydantic and FastAPI to explicitly declare that a value is required.
+
 This will let **FastAPI** know that this parameter is required.
 
+### Required with `None`
+
+You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
+
+To do that, you can declare that `None` is a valid type but still use `default=...`:
+
+=== "Python 3.6 and above"
+
+    ```Python hl_lines="8"
+    {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
+    ```
+
+=== "Python 3.10 and above"
+
+    ```Python hl_lines="7"
+    {!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
+    ```
+
+!!! tip
+    Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
+
+### Use Pydantic's `Required` instead of Ellipsis (`...`)
+
+If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic:
+
+```Python hl_lines="2  8"
+{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
+```
+
+!!! tip
+    Remember that in most of the cases, when something is required, you can simply omit the `default` parameter, so you normally don't have to use `...` nor `Required`.
+
 ## Query parameter list / multiple values
 
 When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
@@ -315,7 +357,7 @@ You can add a `title`:
 
 === "Python 3.10 and above"
 
-    ```Python hl_lines="7"
+    ```Python hl_lines="8"
     {!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
     ```
 
@@ -399,7 +441,7 @@ To exclude a query parameter from the generated OpenAPI schema (and thus, from t
 
 === "Python 3.10 and above"
 
-    ```Python hl_lines="7"
+    ```Python hl_lines="8"
     {!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
     ```
 
index ae101e0a090cdc4e656b26b2ab095009b1bdd513..74a986a6a9bff84a1e1e0d29c96d75f3d861592d 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Body, FastAPI, status
 from fastapi.responses import JSONResponse
@@ -10,7 +10,9 @@ items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "siz
 
 @app.put("/items/{item_id}")
 async def upsert_item(
-    item_id: str, name: Optional[str] = Body(None), size: Optional[int] = Body(None)
+    item_id: str,
+    name: Union[str, None] = Body(default=None),
+    size: Union[int, None] = Body(default=None),
 ):
     if item_id in items:
         item = items[item_id]
index df43db8060515e358f81cace7fff539051d59a0d..11558b8e813f4e0afecc9bea846b8149ed10e674 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Header, HTTPException
 from pydantic import BaseModel
@@ -16,11 +16,11 @@ app = FastAPI()
 class Item(BaseModel):
     id: str
     title: str
-    description: Optional[str] = None
+    description: Union[str, None] = None
 
 
 @app.get("/items/{item_id}", response_model=Item)
-async def read_main(item_id: str, x_token: str = Header(...)):
+async def read_main(item_id: str, x_token: str = Header()):
     if x_token != fake_secret_token:
         raise HTTPException(status_code=400, detail="Invalid X-Token header")
     if item_id not in fake_db:
@@ -29,7 +29,7 @@ async def read_main(item_id: str, x_token: str = Header(...)):
 
 
 @app.post("/items/", response_model=Item)
-async def create_item(item: Item, x_token: str = Header(...)):
+async def create_item(item: Item, x_token: str = Header()):
     if x_token != fake_secret_token:
         raise HTTPException(status_code=400, detail="Invalid X-Token header")
     if item.id in fake_db:
index d44ab9e7c442a01e1c8ace6522cdb2d77c82056d..b4c72de5c94313487f4070bfb9e1a4ace9b2d935 100644 (file)
@@ -18,7 +18,7 @@ class Item(BaseModel):
 
 
 @app.get("/items/{item_id}", response_model=Item)
-async def read_main(item_id: str, x_token: str = Header(...)):
+async def read_main(item_id: str, x_token: str = Header()):
     if x_token != fake_secret_token:
         raise HTTPException(status_code=400, detail="Invalid X-Token header")
     if item_id not in fake_db:
@@ -27,7 +27,7 @@ async def read_main(item_id: str, x_token: str = Header(...)):
 
 
 @app.post("/items/", response_model=Item)
-async def create_item(item: Item, x_token: str = Header(...)):
+async def create_item(item: Item, x_token: str = Header()):
     if x_token != fake_secret_token:
         raise HTTPException(status_code=400, detail="Invalid X-Token header")
     if item.id in fake_db:
index 267b0d3a8ee20a4409fa6539ee3e8f1b8ade43d1..8e45f004b42e4b247d9b752f49a1cf960da2b4cb 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import Header, HTTPException
 
 
-async def get_token_header(x_token: str = Header(...)):
+async def get_token_header(x_token: str = Header()):
     if x_token != "fake-super-secret-token":
         raise HTTPException(status_code=400, detail="X-Token header invalid")
 
index dabc48a0f5a64c7a8b27766f52c2904d7762ac39..cbeebd614ad53643230f8799bff2ef9c68e53f70 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Body, FastAPI
 from pydantic import BaseModel, Field
@@ -8,14 +8,14 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: Optional[str] = Field(
-        None, title="The description of the item", max_length=300
+    description: Union[str, None] = Field(
+        default=None, title="The description of the item", max_length=300
     )
-    price: float = Field(..., gt=0, description="The price must be greater than zero")
-    tax: Optional[float] = None
+    price: float = Field(gt=0, description="The price must be greater than zero")
+    tax: Union[float, None] = None
 
 
 @app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(embed=True)):
     results = {"item_id": item_id, "item": item}
     return results
index 01e02a050d8206234eefc167aaa19e30c015ea94..4437327f3bf828c28c35088957a5de39c5b4104e 100644 (file)
@@ -7,13 +7,13 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     description: str | None = Field(
-        None, title="The description of the item", max_length=300
+        default=None, title="The description of the item", max_length=300
     )
-    price: float = Field(..., gt=0, description="The price must be greater than zero")
+    price: float = Field(gt=0, description="The price must be greater than zero")
     tax: float | None = None
 
 
 @app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(embed=True)):
     results = {"item_id": item_id, "item": item}
     return results
index 7ce0ae6f28483ed9b7a037d6a407498958b05bad..a73975b3a2b3b29a6e0bf82e70cbae572caa93a3 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Path
 from pydantic import BaseModel
@@ -8,17 +8,17 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: Optional[str] = None
+    description: Union[str, None] = None
     price: float
-    tax: Optional[float] = None
+    tax: Union[float, None] = None
 
 
 @app.put("/items/{item_id}")
 async def update_item(
     *,
-    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
-    q: Optional[str] = None,
-    item: Optional[Item] = None,
+    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
+    q: Union[str, None] = None,
+    item: Union[Item, None] = None,
 ):
     results = {"item_id": item_id}
     if q:
index b08d397b3a4db84118de424a68ab4411c1892345..be0eba2aee846704d1cbb7b52b170c525eb84354 100644 (file)
@@ -14,7 +14,7 @@ class Item(BaseModel):
 @app.put("/items/{item_id}")
 async def update_item(
     *,
-    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
+    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
     q: str | None = None,
     item: Item | None = None,
 ):
index 7e9e2437481255d83531e76c8a0356c5337e9b84..cf344e6c5d010c32ec3f02ac1a5f8c63c2fe89d0 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
@@ -8,19 +8,17 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: Optional[str] = None
+    description: Union[str, None] = None
     price: float
-    tax: Optional[float] = None
+    tax: Union[float, None] = None
 
 
 class User(BaseModel):
     username: str
-    full_name: Optional[str] = None
+    full_name: Union[str, None] = None
 
 
 @app.put("/items/{item_id}")
-async def update_item(
-    item_id: int, item: Item, user: User, importance: int = Body(...)
-):
+async def update_item(item_id: int, item: Item, user: User, importance: int = Body()):
     results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
     return results
index 9ddbda3f7b2ed2fa894f49b082860e260bb42899..a1a75fe8e40e9067147ac0735b70ad380ea292e5 100644 (file)
@@ -17,8 +17,6 @@ class User(BaseModel):
 
 
 @app.put("/items/{item_id}")
-async def update_item(
-    item_id: int, item: Item, user: User, importance: int = Body(...)
-):
+async def update_item(item_id: int, item: Item, user: User, importance: int = Body()):
     results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
     return results
index 8dc0d374dedddebea249813e4301607e6fda1f9d..beea7d1e38ff89b95418697f7fa416ea84930816 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
@@ -8,14 +8,14 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: Optional[str] = None
+    description: Union[str, None] = None
     price: float
-    tax: Optional[float] = None
+    tax: Union[float, None] = None
 
 
 class User(BaseModel):
     username: str
-    full_name: Optional[str] = None
+    full_name: Union[str, None] = None
 
 
 @app.put("/items/{item_id}")
@@ -24,8 +24,8 @@ async def update_item(
     item_id: int,
     item: Item,
     user: User,
-    importance: int = Body(..., gt=0),
-    q: Optional[str] = None
+    importance: int = Body(gt=0),
+    q: Union[str, None] = None
 ):
     results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
     if q:
index 77321300e68f2c228d8ef26a38d519aae0292ede..6d495d4082352b8c41dbcd6d12f9ac90d7d0f205 100644 (file)
@@ -22,7 +22,7 @@ async def update_item(
     item_id: int,
     item: Item,
     user: User,
-    importance: int = Body(..., gt=0),
+    importance: int = Body(gt=0),
     q: str | None = None
 ):
     results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
index 4657b4144e4c60464d01513f447f981bb91b48bc..29e6e14b7e306571b35c99237165e1e06df9df2d 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
@@ -8,12 +8,12 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: Optional[str] = None
+    description: Union[str, None] = None
     price: float
-    tax: Optional[float] = None
+    tax: Union[float, None] = None
 
 
 @app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(embed=True)):
     results = {"item_id": item_id, "item": item}
     return results
index 97b213b16375dad709f891456ce370aa6e73d88a..06744507b8e28ff4cf47c927e4a5b526deb64461 100644 (file)
@@ -12,6 +12,6 @@ class Item(BaseModel):
 
 
 @app.put("/items/{item_id}")
-async def update_item(item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(embed=True)):
     results = {"item_id": item_id, "item": item}
     return results
index 67d03b13366a2ef5628f4152e0a3988700635e6b..c4a497fda5989eec92c81a8fcd7978742e54834c 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import Cookie, FastAPI
 
@@ -6,5 +6,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(ads_id: Optional[str] = Cookie(None)):
+async def read_items(ads_id: Union[str, None] = Cookie(default=None)):
     return {"ads_id": ads_id}
index d0b004631816068a267a2399b1deb82bae1d86e7..6c9d5f9a1ebcb22a738294ad319c49a6ca7742aa 100644 (file)
@@ -4,5 +4,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(ads_id: str | None = Cookie(None)):
+async def read_items(ads_id: str | None = Cookie(default=None)):
     return {"ads_id": ads_id}
index 2e64ad45d8b5648474c5d0ff6f98bab47dc32370..268ce9019e9e8a57a4115821225a71fa311d7662 100644 (file)
@@ -31,5 +31,5 @@ app.router.route_class = GzipRoute
 
 
 @app.post("/sum")
-async def sum_numbers(numbers: List[int] = Body(...)):
+async def sum_numbers(numbers: List[int] = Body()):
     return {"sum": sum(numbers)}
index f4c093ac9c6e5b9cc112edb67e3634f0ede10095..cee4a95f088c74a6343995d8da123a45892b2dc1 100644 (file)
@@ -25,5 +25,5 @@ app.router.route_class = ValidationErrorLoggingRoute
 
 
 @app.post("/")
-async def sum_numbers(numbers: List[int] = Body(...)):
+async def sum_numbers(numbers: List[int] = Body()):
     return sum(numbers)
index c8923d143dcdb2090987c3a196f5fd74396ee714..24f73c61780325948b4df79a0e0b67d6daf663bc 100644 (file)
@@ -10,7 +10,7 @@ def query_extractor(q: Optional[str] = None):
 
 
 def query_or_cookie_extractor(
-    q: str = Depends(query_extractor), last_query: Optional[str] = Cookie(None)
+    q: str = Depends(query_extractor), last_query: Optional[str] = Cookie(default=None)
 ):
     if not q:
         return last_query
index 5e1d7e0ef042325d867611d4c29b208bb7fb190b..247cdabe213a8f0fd6b7415a07a7af64f4bf4590 100644 (file)
@@ -8,7 +8,7 @@ def query_extractor(q: str | None = None):
 
 
 def query_or_cookie_extractor(
-    q: str = Depends(query_extractor), last_query: str | None = Cookie(None)
+    q: str = Depends(query_extractor), last_query: str | None = Cookie(default=None)
 ):
     if not q:
         return last_query
index a71d7cce6ea5d3df6b7debcf58460a5f62fe046b..9aff4154f44360c9b7b61c6335af368d3fcd8316 100644 (file)
@@ -3,12 +3,12 @@ from fastapi import Depends, FastAPI, Header, HTTPException
 app = FastAPI()
 
 
-async def verify_token(x_token: str = Header(...)):
+async def verify_token(x_token: str = Header()):
     if x_token != "fake-super-secret-token":
         raise HTTPException(status_code=400, detail="X-Token header invalid")
 
 
-async def verify_key(x_key: str = Header(...)):
+async def verify_key(x_key: str = Header()):
     if x_key != "fake-super-secret-key":
         raise HTTPException(status_code=400, detail="X-Key header invalid")
     return x_key
index 8f8868a559e3f08b0b1497c6a6e60e53ca28c36b..36ce6c7111e6706691295372b39b1f5df1b21305 100644 (file)
@@ -1,12 +1,12 @@
 from fastapi import Depends, FastAPI, Header, HTTPException
 
 
-async def verify_token(x_token: str = Header(...)):
+async def verify_token(x_token: str = Header()):
     if x_token != "fake-super-secret-token":
         raise HTTPException(status_code=400, detail="X-Token header invalid")
 
 
-async def verify_key(x_key: str = Header(...)):
+async def verify_key(x_key: str = Header()):
     if x_key != "fake-super-secret-key":
         raise HTTPException(status_code=400, detail="X-Key header invalid")
     return x_key
index e8d7e1ea3247562c491931343a13298e13dd0465..9f5e911bfab02f406a14d7e3ca1b962e61760ce8 100644 (file)
@@ -10,10 +10,10 @@ app = FastAPI()
 @app.put("/items/{item_id}")
 async def read_items(
     item_id: UUID,
-    start_datetime: Optional[datetime] = Body(None),
-    end_datetime: Optional[datetime] = Body(None),
-    repeat_at: Optional[time] = Body(None),
-    process_after: Optional[timedelta] = Body(None),
+    start_datetime: Optional[datetime] = Body(default=None),
+    end_datetime: Optional[datetime] = Body(default=None),
+    repeat_at: Optional[time] = Body(default=None),
+    process_after: Optional[timedelta] = Body(default=None),
 ):
     start_process = start_datetime + process_after
     duration = end_datetime - start_process
index 4a33481b77d47c61230863bc411df538fdfa2a76..d22f818886d9d078b216388871c01042cfcc230b 100644 (file)
@@ -9,10 +9,10 @@ app = FastAPI()
 @app.put("/items/{item_id}")
 async def read_items(
     item_id: UUID,
-    start_datetime: datetime | None = Body(None),
-    end_datetime: datetime | None = Body(None),
-    repeat_at: time | None = Body(None),
-    process_after: timedelta | None = Body(None),
+    start_datetime: datetime | None = Body(default=None),
+    end_datetime: datetime | None = Body(default=None),
+    repeat_at: time | None = Body(default=None),
+    process_after: timedelta | None = Body(default=None),
 ):
     start_process = start_datetime + process_after
     duration = end_datetime - start_process
index 7d69b027eec5b606a59cc4493ae6f0d5fe9aca52..1df561a12fb30c0be335ca6fded2f03fdec4e96c 100644 (file)
@@ -6,5 +6,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(user_agent: Optional[str] = Header(None)):
+async def read_items(user_agent: Optional[str] = Header(default=None)):
     return {"User-Agent": user_agent}
index b2846334659fb0b7f654d15df87b0cfa708e05ee..2203ed1b8b62b154aacdad1eb9b0d33fa1cf8f2a 100644 (file)
@@ -4,5 +4,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(user_agent: str | None = Header(None)):
+async def read_items(user_agent: str | None = Header(default=None)):
     return {"User-Agent": user_agent}
index 2de3dddd70ac6fda000571a9967a9217caf00b88..2250727f6d598c496833902ff0168a117add68fe 100644 (file)
@@ -7,6 +7,6 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    strange_header: Optional[str] = Header(None, convert_underscores=False)
+    strange_header: Optional[str] = Header(default=None, convert_underscores=False)
 ):
     return {"strange_header": strange_header}
index 98ab5a807d6a5e39d2af6f93e76653408c947d31..b7979b542a1439716032ad5bca5f32adb896b2f4 100644 (file)
@@ -5,6 +5,6 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    strange_header: str | None = Header(None, convert_underscores=False)
+    strange_header: str | None = Header(default=None, convert_underscores=False)
 ):
     return {"strange_header": strange_header}
index 6d0eefdd2141a2c626bff785b562bd3ecf37eb88..1ef131cee3c14ad97082f86371f50256e2c02c5f 100644 (file)
@@ -6,5 +6,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(x_token: Optional[List[str]] = Header(None)):
+async def read_items(x_token: Optional[List[str]] = Header(default=None)):
     return {"X-Token values": x_token}
index 2dac2c13cf186a18104a0aa6b47ba87d9db87c21..435c67574b0cdc93058916e6ee8059eaec81ae26 100644 (file)
@@ -4,5 +4,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(x_token: list[str] | None = Header(None)):
+async def read_items(x_token: list[str] | None = Header(default=None)):
     return {"X-Token values": x_token}
index 359766527eb87e548683b7cbe3a82f1ac3ef1ad0..78dda58da49f91475e154cb32fce9acc79600755 100644 (file)
@@ -6,5 +6,5 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(x_token: Optional[list[str]] = Header(None)):
+async def read_items(x_token: Optional[list[str]] = Header(default=None)):
     return {"X-Token values": x_token}
index 11777bba77b9934a2903b145342b117dfbe4c6ac..53014702826e37b3450ec180daef58953a658a4e 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Path, Query
 
@@ -7,8 +7,8 @@ app = FastAPI()
 
 @app.get("/items/{item_id}")
 async def read_items(
-    item_id: int = Path(..., title="The ID of the item to get"),
-    q: Optional[str] = Query(None, alias="item-query"),
+    item_id: int = Path(title="The ID of the item to get"),
+    q: Union[str, None] = Query(default=None, alias="item-query"),
 ):
     results = {"item_id": item_id}
     if q:
index b940a0949f6decba8c0f692f40e298c475e4860a..b1a77cc9dd1df7bc27a61264d3c423da33504744 100644 (file)
@@ -5,8 +5,8 @@ app = FastAPI()
 
 @app.get("/items/{item_id}")
 async def read_items(
-    item_id: int = Path(..., title="The ID of the item to get"),
-    q: str | None = Query(None, alias="item-query"),
+    item_id: int = Path(title="The ID of the item to get"),
+    q: str | None = Query(default=None, alias="item-query"),
 ):
     results = {"item_id": item_id}
     if q:
index 57ca50ece01794693dfe8e5190595ff983b14c79..63ac691a8347ea97c6efa713a5c8c4e595a98254 100644 (file)
@@ -4,9 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/{item_id}")
-async def read_items(
-    q: str, item_id: int = Path(..., title="The ID of the item to get")
-):
+async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
     results = {"item_id": item_id}
     if q:
         results.update({"q": q})
index b6b5a19869b0da5391166068ee875aee23d32048..8df0ffc6202bdfd9ae3180ed77fadaea84de4a60 100644 (file)
@@ -4,9 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/{item_id}")
-async def read_items(
-    *, item_id: int = Path(..., title="The ID of the item to get"), q: str
-):
+async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
     results = {"item_id": item_id}
     if q:
         results.update({"q": q})
index 2ec70828013e56faa8ae5df7caf4a358ebc69fd7..86651d47cfee2df98f18d25fd66281fe75760b36 100644 (file)
@@ -5,7 +5,7 @@ app = FastAPI()
 
 @app.get("/items/{item_id}")
 async def read_items(
-    *, item_id: int = Path(..., title="The ID of the item to get", ge=1), q: str
+    *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
 ):
     results = {"item_id": item_id}
     if q:
index 2809f37b27ed3520be0e3d41392d6d8482d68757..8f12f2da026596de43c37e25629b5a9d4ddf0b3c 100644 (file)
@@ -6,7 +6,7 @@ app = FastAPI()
 @app.get("/items/{item_id}")
 async def read_items(
     *,
-    item_id: int = Path(..., title="The ID of the item to get", gt=0, le=1000),
+    item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
     q: str,
 ):
     results = {"item_id": item_id}
index 0c19579f5e3b21bf5a843ee58f9fcbb55313adf3..85bd6e8b4d258609c6ab3917555031abf032450f 100644 (file)
@@ -6,9 +6,9 @@ app = FastAPI()
 @app.get("/items/{item_id}")
 async def read_items(
     *,
-    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
+    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
     q: str,
-    size: float = Query(..., gt=0, lt=10.5)
+    size: float = Query(gt=0, lt=10.5)
 ):
     results = {"item_id": item_id}
     if q:
index 68ea582061a00740a7c74eb5c4cda3a2ff82147d..17e017b7e7142b5b88ea37f1033e84f9ad7076f4 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -6,7 +6,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: Optional[str] = Query(None, max_length=50)):
+async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index fa3139d5aadf7b70e3010ec97f0597b72f7288c6..f15351d290ee920358109d4e3bfa91243aa78358 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str | None = Query(None, max_length=50)):
+async def read_items(q: str | None = Query(default=None, max_length=50)):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index e52acc72f0fea091704abab8676b995564542fd6..73d2e08c8ef0d33cc74dc1796a52440e5fad8f2b 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -6,7 +6,9 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: Optional[str] = Query(None, min_length=3, max_length=50)):
+async def read_items(
+    q: Union[str, None] = Query(default=None, min_length=3, max_length=50)
+):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index 335858a404c92710815939e8fd79b02b07c08482..dc60ecb39da7bf8c506088d454213f7ac5159858 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str | None = Query(None, min_length=3, max_length=50)):
+async def read_items(q: str | None = Query(default=None, min_length=3, max_length=50)):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index d2c30331f63a00e61b3ac95e26103e85e90e5647..5a7129816c4a602e9dc239ff50753484ba8bedb6 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -7,7 +7,9 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: Optional[str] = Query(None, min_length=3, max_length=50, regex="^fixedquery$")
+    q: Union[str, None] = Query(
+        default=None, min_length=3, max_length=50, regex="^fixedquery$"
+    )
 ):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
index 518b779f70ff64fd2590b74a0188552c7f00396f..180a2e5112a0bb94dcbc78f3d82220ff42995ace 100644 (file)
@@ -5,7 +5,8 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: str | None = Query(None, min_length=3, max_length=50, regex="^fixedquery$")
+    q: str
+    | None = Query(default=None, min_length=3, max_length=50, regex="^fixedquery$")
 ):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
index 22eb3acba16c9ff9a543adba1f6879838490d4f9..8ab42869e6140140ec6bc4c71a6c37fe119caabb 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str = Query("fixedquery", min_length=3)):
+async def read_items(q: str = Query(default="fixedquery", min_length=3)):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index 720bf07f1a9dfd6e3ec9fb2724dcc00cd991bc5b..9a90eb64efafa641ff78d95a00ddea8763f91418 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str = Query(..., min_length=3)):
+async def read_items(q: str = Query(min_length=3)):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006b.py b/docs_src/query_params_str_validations/tutorial006b.py
new file mode 100644 (file)
index 0000000..a8d69c8
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+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})
+    return results
diff --git a/docs_src/query_params_str_validations/tutorial006c.py b/docs_src/query_params_str_validations/tutorial006c.py
new file mode 100644 (file)
index 0000000..2ac148c
--- /dev/null
@@ -0,0 +1,13 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Union[str, None] = Query(default=..., min_length=3)):
+    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+    if q:
+        results.update({"q": q})
+    return results
diff --git a/docs_src/query_params_str_validations/tutorial006c_py310.py b/docs_src/query_params_str_validations/tutorial006c_py310.py
new file mode 100644 (file)
index 0000000..82dd9e5
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: str | None = Query(default=..., min_length=3)):
+    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+    if q:
+        results.update({"q": q})
+    return results
diff --git a/docs_src/query_params_str_validations/tutorial006d.py b/docs_src/query_params_str_validations/tutorial006d.py
new file mode 100644 (file)
index 0000000..42c5bf4
--- /dev/null
@@ -0,0 +1,12 @@
+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)):
+    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+    if q:
+        results.update({"q": q})
+    return results
index e360feda9f07a1852ef98847541a83fdfcf3e6a0..cb836569e980e0ad913fb2f6d20c2810e019aab3 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -7,7 +7,7 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: Optional[str] = Query(None, title="Query string", min_length=3)
+    q: Union[str, None] = Query(default=None, title="Query string", min_length=3)
 ):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
index 14ef4cb69fc332b733b3e7d0776bc1f5ac98d23c..e3e1ef2e087116b42e7c8346b98834573c952123 100644 (file)
@@ -4,7 +4,9 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str | None = Query(None, title="Query string", min_length=3)):
+async def read_items(
+    q: str | None = Query(default=None, title="Query string", min_length=3)
+):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index 238add47104259bfb3aa74a4dc900614a37b980b..d112a9ab8aa5ad983cf1418885d48a730a02894a 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -7,8 +7,8 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: Optional[str] = Query(
-        None,
+    q: Union[str, None] = Query(
+        default=None,
         title="Query string",
         description="Query string for the items to search in the database that have a good match",
         min_length=3,
index 06bb02442bde82864eca1ba97c1ea4b06561e402..489f631d5e90875a5b9128dffbd7aac973c50317 100644 (file)
@@ -7,7 +7,7 @@ app = FastAPI()
 async def read_items(
     q: str
     | None = Query(
-        None,
+        default=None,
         title="Query string",
         description="Query string for the items to search in the database that have a good match",
         min_length=3,
index 7e5c0b81a8a8421ee4f9af2b2e591442ea080a60..8a6bfe2d93fb34ee005b18c6c7623c58c8168a02 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -6,7 +6,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: Optional[str] = Query(None, alias="item-query")):
+async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index e84c116f127603284d1c3b8f073e96f8b5e909ed..a38d32cbbd2b6e4d6d9f0f65fb4f85aa015c87bb 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: str | None = Query(None, alias="item-query")):
+async def read_items(q: str | None = Query(default=None, alias="item-query")):
     results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
     if q:
         results.update({"q": q})
index 7921506b653d47152199894f722bad4954d84c65..35443d19470614a20268334a4bb07401f7fb0b98 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -7,8 +7,8 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: Optional[str] = Query(
-        None,
+    q: Union[str, None] = Query(
+        default=None,
         alias="item-query",
         title="Query string",
         description="Query string for the items to search in the database that have a good match",
index c35800858d1227e39509efdc2da5b112286c59d4..f2839516e64466b270dba73cb78f25e92fa74301 100644 (file)
@@ -7,7 +7,7 @@ app = FastAPI()
 async def read_items(
     q: str
     | None = Query(
-        None,
+        default=None,
         alias="item-query",
         title="Query string",
         description="Query string for the items to search in the database that have a good match",
index 7fda267edd59db649b1c9aa23df72e3643d365b0..65bbce781ac41f5ef02e9695499557280e2babf8 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import List, Union
 
 from fastapi import FastAPI, Query
 
@@ -6,6 +6,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: Optional[List[str]] = Query(None)):
+async def read_items(q: Union[List[str], None] = Query(default=None)):
     query_items = {"q": q}
     return query_items
index c3d992e625b6d05b61baa611d41880b8abcd94da..70155de7c9a2862fce57447bdfd03c560ff441d8 100644 (file)
@@ -4,6 +4,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: list[str] | None = Query(None)):
+async def read_items(q: list[str] | None = Query(default=None)):
     query_items = {"q": q}
     return query_items
index 38ba764d6fcf2ac85d2fee1713799e396dc5b466..878f95c7984cf8515321b71e555299db6f072ae6 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -6,6 +6,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: Optional[list[str]] = Query(None)):
+async def read_items(q: Union[list[str], None] = Query(default=None)):
     query_items = {"q": q}
     return query_items
index 7ea9f017dfa6e1b84f85061f2e4f221b6255fcfb..e77d56974de912739835dfeac120ed5dfa4f4a35 100644 (file)
@@ -6,6 +6,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: List[str] = Query(["foo", "bar"])):
+async def read_items(q: List[str] = Query(default=["foo", "bar"])):
     query_items = {"q": q}
     return query_items
index 1900133d9f7687e603d7b99b650ca4db2482cf21..070d0b04bfd03372871989770bd0e8a14616dde7 100644 (file)
@@ -4,6 +4,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: list[str] = Query(["foo", "bar"])):
+async def read_items(q: list[str] = Query(default=["foo", "bar"])):
     query_items = {"q": q}
     return query_items
index 95dd6999dd0f4ca7d71f477b3ad850e06acb51e3..0b0f44869fd5fbec5a02beb102c870fb28a31fed 100644 (file)
@@ -4,6 +4,6 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(q: list = Query([])):
+async def read_items(q: list = Query(default=[])):
     query_items = {"q": q}
     return query_items
index fb50bc27b56397a716c3bf3e4d788537ab71d42b..50e0a6c2b18cebcf70b6b9229b2844666e5599e6 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import Union
 
 from fastapi import FastAPI, Query
 
@@ -7,7 +7,7 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    hidden_query: Optional[str] = Query(None, include_in_schema=False)
+    hidden_query: Union[str, None] = Query(default=None, include_in_schema=False)
 ):
     if hidden_query:
         return {"hidden_query": hidden_query}
index 7ae39c7f97e1642ae960dc3a226d3e6f4c57cb7d..1b617efdd128a043e7f06ccb863b33fe92fc3986 100644 (file)
@@ -4,7 +4,9 @@ app = FastAPI()
 
 
 @app.get("/items/")
-async def read_items(hidden_query: str | None = Query(None, include_in_schema=False)):
+async def read_items(
+    hidden_query: str | None = Query(default=None, include_in_schema=False)
+):
     if hidden_query:
         return {"hidden_query": hidden_query}
     else:
index 0fb1dd571b1b021130d8118a10cd81aabfc3bf96..2e0ea6391278d500b05d6f2f90afcc71d1f06ae7 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_file(file: bytes = File(...)):
+async def create_file(file: bytes = File()):
     return {"file_size": len(file)}
 
 
index 26a4c9cbf069d16b9a43af78744d255036f2e27b..3f311c4b853f1674391ca0ae48af3fd29342e5b7 100644 (file)
@@ -6,7 +6,7 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_file(file: Optional[bytes] = File(None)):
+async def create_file(file: Optional[bytes] = File(default=None)):
     if not file:
         return {"message": "No file sent"}
     else:
index 0e576251b57b332277e8ec51647deda6d1d70f69..298c9974f2fe989e3d5686a2ce50e04d3ba8da8d 100644 (file)
@@ -4,7 +4,7 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_file(file: bytes | None = File(None)):
+async def create_file(file: bytes | None = File(default=None)):
     if not file:
         return {"message": "No file sent"}
     else:
index abcac9e4c1cb29da476e4a5d52ee6dcbda4d14aa..d8005cc7d2822615cb68cc866f20a7683ddfdd45 100644 (file)
@@ -4,12 +4,12 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_file(file: bytes = File(..., description="A file read as bytes")):
+async def create_file(file: bytes = File(description="A file read as bytes")):
     return {"file_size": len(file)}
 
 
 @app.post("/uploadfile/")
 async def create_upload_file(
-    file: UploadFile = File(..., description="A file read as UploadFile")
+    file: UploadFile = File(description="A file read as UploadFile"),
 ):
     return {"filename": file.filename}
index 94abb7c6c0492eca74598e7b7d8c508c9e4636b7..b4d0acc68f1ade150ecb9c8f8e9e4ac28b5a53db 100644 (file)
@@ -7,7 +7,7 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_files(files: List[bytes] = File(...)):
+async def create_files(files: List[bytes] = File()):
     return {"file_sizes": [len(file) for file in files]}
 
 
index 2779618bde83f93e958fabfd09aa27b923399605..b64cf55987898b7fb2538f527efd5e1034c4198a 100644 (file)
@@ -5,7 +5,7 @@ app = FastAPI()
 
 
 @app.post("/files/")
-async def create_files(files: list[bytes] = File(...)):
+async def create_files(files: list[bytes] = File()):
     return {"file_sizes": [len(file) for file in files]}
 
 
index 4a91b7a8bc611dbb1a21c4b5538c9f87593429da..e3f805f605262e439a3b473f1ca579ab21840662 100644 (file)
@@ -8,14 +8,14 @@ app = FastAPI()
 
 @app.post("/files/")
 async def create_files(
-    files: List[bytes] = File(..., description="Multiple files as bytes")
+    files: List[bytes] = File(description="Multiple files as bytes"),
 ):
     return {"file_sizes": [len(file) for file in files]}
 
 
 @app.post("/uploadfiles/")
 async def create_upload_files(
-    files: List[UploadFile] = File(..., description="Multiple files as UploadFile")
+    files: List[UploadFile] = File(description="Multiple files as UploadFile"),
 ):
     return {"filenames": [file.filename for file in files]}
 
index d853f48d1135714070c631e6e476efe13837ec63..96f5e8742dcfc3cea29cefbadb7a19352bb0bcb5 100644 (file)
@@ -6,14 +6,14 @@ app = FastAPI()
 
 @app.post("/files/")
 async def create_files(
-    files: list[bytes] = File(..., description="Multiple files as bytes")
+    files: list[bytes] = File(description="Multiple files as bytes"),
 ):
     return {"file_sizes": [len(file) for file in files]}
 
 
 @app.post("/uploadfiles/")
 async def create_upload_files(
-    files: list[UploadFile] = File(..., description="Multiple files as UploadFile")
+    files: list[UploadFile] = File(description="Multiple files as UploadFile"),
 ):
     return {"filenames": [file.filename for file in files]}
 
index c07e2294585eb317a0c621f0b241fc48f63d37a9..a537700019d173bb437f492256573a5005ab5f3e 100644 (file)
@@ -4,5 +4,5 @@ app = FastAPI()
 
 
 @app.post("/login/")
-async def login(username: str = Form(...), password: str = Form(...)):
+async def login(username: str = Form(), password: str = Form()):
     return {"username": username}
index 5bf3a5bc0530ee41a46cd503b4c7ffcea6c00c43..7b5224ce5358396649ff08fbadb8a69825a9a707 100644 (file)
@@ -5,7 +5,7 @@ app = FastAPI()
 
 @app.post("/files/")
 async def create_file(
-    file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...)
+    file: bytes = File(), fileb: UploadFile = File(), token: str = Form()
 ):
     return {
         "file_size": len(file),
index df3df8854719ade24d04229ee7148eb8873de4f9..a2aec46f54fe498c3316ef06a5288dd1a20865bb 100644 (file)
@@ -7,10 +7,10 @@ app = FastAPI()
 
 
 class Item(BaseModel):
-    name: str = Field(..., example="Foo")
-    description: Optional[str] = Field(None, example="A very nice Item")
-    price: float = Field(..., example=35.4)
-    tax: Optional[float] = Field(None, example=3.2)
+    name: str = Field(example="Foo")
+    description: Optional[str] = Field(default=None, example="A very nice Item")
+    price: float = Field(example=35.4)
+    tax: Optional[float] = Field(default=None, example=3.2)
 
 
 @app.put("/items/{item_id}")
index 4f8f8304ec82db3654cd4733379a925d984466f5..e84928bb11980c989aafe14394870e6ffa811beb 100644 (file)
@@ -5,10 +5,10 @@ app = FastAPI()
 
 
 class Item(BaseModel):
-    name: str = Field(..., example="Foo")
-    description: str | None = Field(None, example="A very nice Item")
-    price: float = Field(..., example=35.4)
-    tax: float | None = Field(None, example=3.2)
+    name: str = Field(example="Foo")
+    description: str | None = Field(default=None, example="A very nice Item")
+    price: float = Field(example=35.4)
+    tax: float | None = Field(default=None, example=3.2)
 
 
 @app.put("/items/{item_id}")
index 58c79f55439f2dba843ce08b5781067759fc7e87..43d46b81ba953a2f6328e06fc19fc846ac0db271 100644 (file)
@@ -17,7 +17,6 @@ class Item(BaseModel):
 async def update_item(
     item_id: int,
     item: Item = Body(
-        ...,
         example={
             "name": "Foo",
             "description": "A very nice Item",
index cf4c99dc033f6085d9dd0106873f9739baa3bd81..1e137101d9e465aef37b532f78d45dfadf95e2ea 100644 (file)
@@ -15,7 +15,6 @@ class Item(BaseModel):
 async def update_item(
     item_id: int,
     item: Item = Body(
-        ...,
         example={
             "name": "Foo",
             "description": "A very nice Item",
index 9f0e8b43787a1b2870d207328b422e6ff547ed66..42d7a04a3c1d3455e150169130d750f221d6949d 100644 (file)
@@ -18,7 +18,6 @@ async def update_item(
     *,
     item_id: int,
     item: Item = Body(
-        ...,
         examples={
             "normal": {
                 "summary": "A normal example",
index 6f29c1a5c67d340b41f0aac9edf1da0acf3c5467..100a30860b01a18c96b0fa0cd072b7feff8408f5 100644 (file)
@@ -16,7 +16,6 @@ async def update_item(
     *,
     item_id: int,
     item: Item = Body(
-        ...,
         examples={
             "normal": {
                 "summary": "A normal example",
index 53cdb41ff1b54e910b539246401f4b0fa75d396f..b010085303b2ba44ccf582667ac792eeb962fe3b 100644 (file)
@@ -57,8 +57,8 @@ async def get():
 
 async def get_cookie_or_token(
     websocket: WebSocket,
-    session: Optional[str] = Cookie(None),
-    token: Optional[str] = Query(None),
+    session: Optional[str] = Cookie(default=None),
+    token: Optional[str] = Query(default=None),
 ):
     if session is None and token is None:
         await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
index 9dccd354efe7e2c2ac89286db586f503d544a6b4..f397e333c09286ecbc698e17e21064fb686cee57 100644 (file)
@@ -43,6 +43,7 @@ from pydantic.fields import (
     FieldInfo,
     ModelField,
     Required,
+    Undefined,
 )
 from pydantic.schema import get_annotation_from_field_info
 from pydantic.typing import ForwardRef, evaluate_forwardref
@@ -316,7 +317,7 @@ def get_dependant(
             field_info = param_field.field_info
             assert isinstance(
                 field_info, params.Body
-            ), f"Param: {param_field.name} can only be a request body, using Body(...)"
+            ), f"Param: {param_field.name} can only be a request body, using Body()"
             dependant.body_params.append(param_field)
     return dependant
 
@@ -353,7 +354,7 @@ def get_param_field(
     force_type: Optional[params.ParamTypes] = None,
     ignore_default: bool = False,
 ) -> ModelField:
-    default_value = Required
+    default_value: Any = Undefined
     had_schema = False
     if not param.default == param.empty and ignore_default is False:
         default_value = param.default
@@ -369,8 +370,13 @@ def get_param_field(
         if force_type:
             field_info.in_ = force_type  # type: ignore
     else:
-        field_info = default_field_info(default_value)
-    required = default_value == Required
+        field_info = default_field_info(default=default_value)
+    required = True
+    if default_value is Required or ignore_default:
+        required = True
+        default_value = None
+    elif default_value is not Undefined:
+        required = False
     annotation: Any = Any
     if not param.annotation == param.empty:
         annotation = param.annotation
@@ -382,12 +388,11 @@ def get_param_field(
     field = create_response_field(
         name=param.name,
         type_=annotation,
-        default=None if required else default_value,
+        default=default_value,
         alias=alias,
         required=required,
         field_info=field_info,
     )
-    field.required = required
     if not had_schema and not is_scalar_field(field=field):
         field.field_info = params.Body(field_info.default)
     if not had_schema and lenient_issubclass(field.type_, UploadFile):
index 9c6598d2d1a7b55c9bf17133f61bc046f03ad5cd..35aa1672b3cc0e6f38505e329bd5ecdf2c4a3fa9 100644 (file)
@@ -73,7 +73,7 @@ class Server(BaseModel):
 
 
 class Reference(BaseModel):
-    ref: str = Field(..., alias="$ref")
+    ref: str = Field(alias="$ref")
 
 
 class Discriminator(BaseModel):
@@ -101,28 +101,28 @@ class ExternalDocumentation(BaseModel):
 
 
 class Schema(BaseModel):
-    ref: Optional[str] = Field(None, alias="$ref")
+    ref: Optional[str] = Field(default=None, alias="$ref")
     title: Optional[str] = None
     multipleOf: Optional[float] = None
     maximum: Optional[float] = None
     exclusiveMaximum: Optional[float] = None
     minimum: Optional[float] = None
     exclusiveMinimum: Optional[float] = None
-    maxLength: Optional[int] = Field(None, gte=0)
-    minLength: Optional[int] = Field(None, gte=0)
+    maxLength: Optional[int] = Field(default=None, gte=0)
+    minLength: Optional[int] = Field(default=None, gte=0)
     pattern: Optional[str] = None
-    maxItems: Optional[int] = Field(None, gte=0)
-    minItems: Optional[int] = Field(None, gte=0)
+    maxItems: Optional[int] = Field(default=None, gte=0)
+    minItems: Optional[int] = Field(default=None, gte=0)
     uniqueItems: Optional[bool] = None
-    maxProperties: Optional[int] = Field(None, gte=0)
-    minProperties: Optional[int] = Field(None, gte=0)
+    maxProperties: Optional[int] = Field(default=None, gte=0)
+    minProperties: Optional[int] = Field(default=None, gte=0)
     required: Optional[List[str]] = None
     enum: Optional[List[Any]] = None
     type: Optional[str] = None
     allOf: Optional[List["Schema"]] = None
     oneOf: Optional[List["Schema"]] = None
     anyOf: Optional[List["Schema"]] = None
-    not_: Optional["Schema"] = Field(None, alias="not")
+    not_: Optional["Schema"] = Field(default=None, alias="not")
     items: Optional[Union["Schema", List["Schema"]]] = None
     properties: Optional[Dict[str, "Schema"]] = None
     additionalProperties: Optional[Union["Schema", Reference, bool]] = None
@@ -171,7 +171,7 @@ class Encoding(BaseModel):
 
 
 class MediaType(BaseModel):
-    schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema")
+    schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
     example: Optional[Any] = None
     examples: Optional[Dict[str, Union[Example, Reference]]] = None
     encoding: Optional[Dict[str, Encoding]] = None
@@ -188,7 +188,7 @@ class ParameterBase(BaseModel):
     style: Optional[str] = None
     explode: Optional[bool] = None
     allowReserved: Optional[bool] = None
-    schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema")
+    schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
     example: Optional[Any] = None
     examples: Optional[Dict[str, Union[Example, Reference]]] = None
     # Serialization rules for more complex scenarios
@@ -200,7 +200,7 @@ class ParameterBase(BaseModel):
 
 class Parameter(ParameterBase):
     name: str
-    in_: ParameterInType = Field(..., alias="in")
+    in_: ParameterInType = Field(alias="in")
 
 
 class Header(ParameterBase):
@@ -258,7 +258,7 @@ class Operation(BaseModel):
 
 
 class PathItem(BaseModel):
-    ref: Optional[str] = Field(None, alias="$ref")
+    ref: Optional[str] = Field(default=None, alias="$ref")
     summary: Optional[str] = None
     description: Optional[str] = None
     get: Optional[Operation] = None
@@ -284,7 +284,7 @@ class SecuritySchemeType(Enum):
 
 
 class SecurityBase(BaseModel):
-    type_: SecuritySchemeType = Field(..., alias="type")
+    type_: SecuritySchemeType = Field(alias="type")
     description: Optional[str] = None
 
     class Config:
@@ -299,7 +299,7 @@ class APIKeyIn(Enum):
 
 class APIKey(SecurityBase):
     type_ = Field(SecuritySchemeType.apiKey, alias="type")
-    in_: APIKeyIn = Field(..., alias="in")
+    in_: APIKeyIn = Field(alias="in")
     name: str
 
 
index a553a1461f8d7605d1acbf9b45ade7246b03b1cf..1932ef0657d66c64e60ff2ffb613fa7ada66fc0b 100644 (file)
@@ -5,7 +5,7 @@ from pydantic.fields import Undefined
 
 
 def Path(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     alias: Optional[str] = None,
     title: Optional[str] = None,
@@ -44,7 +44,7 @@ def Path(  # noqa: N802
 
 
 def Query(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     alias: Optional[str] = None,
     title: Optional[str] = None,
@@ -63,7 +63,7 @@ def Query(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.Query(
-        default,
+        default=default,
         alias=alias,
         title=title,
         description=description,
@@ -83,7 +83,7 @@ def Query(  # noqa: N802
 
 
 def Header(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     alias: Optional[str] = None,
     convert_underscores: bool = True,
@@ -103,7 +103,7 @@ def Header(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.Header(
-        default,
+        default=default,
         alias=alias,
         convert_underscores=convert_underscores,
         title=title,
@@ -124,7 +124,7 @@ def Header(  # noqa: N802
 
 
 def Cookie(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     alias: Optional[str] = None,
     title: Optional[str] = None,
@@ -143,7 +143,7 @@ def Cookie(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.Cookie(
-        default,
+        default=default,
         alias=alias,
         title=title,
         description=description,
@@ -163,7 +163,7 @@ def Cookie(  # noqa: N802
 
 
 def Body(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     embed: bool = False,
     media_type: str = "application/json",
@@ -182,7 +182,7 @@ def Body(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.Body(
-        default,
+        default=default,
         embed=embed,
         media_type=media_type,
         alias=alias,
@@ -202,7 +202,7 @@ def Body(  # noqa: N802
 
 
 def Form(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     media_type: str = "application/x-www-form-urlencoded",
     alias: Optional[str] = None,
@@ -220,7 +220,7 @@ def Form(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.Form(
-        default,
+        default=default,
         media_type=media_type,
         alias=alias,
         title=title,
@@ -239,7 +239,7 @@ def Form(  # noqa: N802
 
 
 def File(  # noqa: N802
-    default: Any,
+    default: Any = Undefined,
     *,
     media_type: str = "multipart/form-data",
     alias: Optional[str] = None,
@@ -257,7 +257,7 @@ def File(  # noqa: N802
     **extra: Any,
 ) -> Any:
     return params.File(
-        default,
+        default=default,
         media_type=media_type,
         alias=alias,
         title=title,
index 042bbd42ff8b0a7cefd536c7fd43a3ae70ad28e3..5395b98a39ab146147a8dc7988bc72905193cc85 100644 (file)
@@ -16,7 +16,7 @@ class Param(FieldInfo):
 
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         alias: Optional[str] = None,
         title: Optional[str] = None,
@@ -39,7 +39,7 @@ class Param(FieldInfo):
         self.examples = examples
         self.include_in_schema = include_in_schema
         super().__init__(
-            default,
+            default=default,
             alias=alias,
             title=title,
             description=description,
@@ -62,7 +62,7 @@ class Path(Param):
 
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         alias: Optional[str] = None,
         title: Optional[str] = None,
@@ -82,7 +82,7 @@ class Path(Param):
     ):
         self.in_ = self.in_
         super().__init__(
-            ...,
+            default=...,
             alias=alias,
             title=title,
             description=description,
@@ -106,7 +106,7 @@ class Query(Param):
 
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         alias: Optional[str] = None,
         title: Optional[str] = None,
@@ -125,7 +125,7 @@ class Query(Param):
         **extra: Any,
     ):
         super().__init__(
-            default,
+            default=default,
             alias=alias,
             title=title,
             description=description,
@@ -149,7 +149,7 @@ class Header(Param):
 
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         alias: Optional[str] = None,
         convert_underscores: bool = True,
@@ -170,7 +170,7 @@ class Header(Param):
     ):
         self.convert_underscores = convert_underscores
         super().__init__(
-            default,
+            default=default,
             alias=alias,
             title=title,
             description=description,
@@ -194,7 +194,7 @@ class Cookie(Param):
 
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         alias: Optional[str] = None,
         title: Optional[str] = None,
@@ -213,7 +213,7 @@ class Cookie(Param):
         **extra: Any,
     ):
         super().__init__(
-            default,
+            default=default,
             alias=alias,
             title=title,
             description=description,
@@ -235,7 +235,7 @@ class Cookie(Param):
 class Body(FieldInfo):
     def __init__(
         self,
-        default: Any,
+        default: Any = Undefined,
         *,
         embed: bool = False,
         media_type: str = "application/json",
@@ -258,7 +258,7 @@ class Body(FieldInfo):
         self.example = example
         self.examples = examples
         super().__init__(
-            default,
+            default=default,
             alias=alias,
             title=title,
             description=description,
@@ -297,7 +297,7 @@ class Form(Body):
         **extra: Any,
     ):
         super().__init__(
-            default,
+            default=default,
             embed=True,
             media_type=media_type,
             alias=alias,
@@ -337,7 +337,7 @@ class File(Form):
         **extra: Any,
     ):
         super().__init__(
-            default,
+            default=default,
             media_type=media_type,
             alias=alias,
             title=title,
index bdc6e2ea9beeefc1126b78aad44dc88a076facd1..888208c1501fce70bc8c93ce14f724076d0ee14c 100644 (file)
@@ -45,12 +45,12 @@ class OAuth2PasswordRequestForm:
 
     def __init__(
         self,
-        grant_type: str = Form(None, regex="password"),
-        username: str = Form(...),
-        password: str = Form(...),
-        scope: str = Form(""),
-        client_id: Optional[str] = Form(None),
-        client_secret: Optional[str] = Form(None),
+        grant_type: str = Form(default=None, regex="password"),
+        username: str = Form(),
+        password: str = Form(),
+        scope: str = Form(default=""),
+        client_id: Optional[str] = Form(default=None),
+        client_secret: Optional[str] = Form(default=None),
     ):
         self.grant_type = grant_type
         self.username = username
@@ -95,12 +95,12 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
 
     def __init__(
         self,
-        grant_type: str = Form(..., regex="password"),
-        username: str = Form(...),
-        password: str = Form(...),
-        scope: str = Form(""),
-        client_id: Optional[str] = Form(None),
-        client_secret: Optional[str] = Form(None),
+        grant_type: str = Form(regex="password"),
+        username: str = Form(),
+        password: str = Form(),
+        scope: str = Form(default=""),
+        client_id: Optional[str] = Form(default=None),
+        client_secret: Optional[str] = Form(default=None),
     ):
         super().__init__(
             grant_type=grant_type,
index 9d720feb3758a25f0db0c849b3bca846c59c51af..a7e135bcab598219cc32740796669ee1dee4f7ce 100644 (file)
@@ -52,7 +52,7 @@ def create_response_field(
     Create a new response field. Raises if type_ is invalid.
     """
     class_validators = class_validators or {}
-    field_info = field_info or FieldInfo(None)
+    field_info = field_info or FieldInfo()
 
     response_field = functools.partial(
         ModelField,
index d5603d0e617e1508f3975034dd60b59d0ac06f76..f70496db8e1118a8641f5a173b38fdd3b02d0c27 100644 (file)
@@ -49,97 +49,97 @@ def get_bool_id(item_id: bool):
 
 
 @app.get("/path/param/{item_id}")
-def get_path_param_id(item_id: Optional[str] = Path(None)):
+def get_path_param_id(item_id: str = Path()):
     return item_id
 
 
 @app.get("/path/param-required/{item_id}")
-def get_path_param_required_id(item_id: str = Path(...)):
+def get_path_param_required_id(item_id: str = Path()):
     return item_id
 
 
 @app.get("/path/param-minlength/{item_id}")
-def get_path_param_min_length(item_id: str = Path(..., min_length=3)):
+def get_path_param_min_length(item_id: str = Path(min_length=3)):
     return item_id
 
 
 @app.get("/path/param-maxlength/{item_id}")
-def get_path_param_max_length(item_id: str = Path(..., max_length=3)):
+def get_path_param_max_length(item_id: str = Path(max_length=3)):
     return item_id
 
 
 @app.get("/path/param-min_maxlength/{item_id}")
-def get_path_param_min_max_length(item_id: str = Path(..., max_length=3, min_length=2)):
+def get_path_param_min_max_length(item_id: str = Path(max_length=3, min_length=2)):
     return item_id
 
 
 @app.get("/path/param-gt/{item_id}")
-def get_path_param_gt(item_id: float = Path(..., gt=3)):
+def get_path_param_gt(item_id: float = Path(gt=3)):
     return item_id
 
 
 @app.get("/path/param-gt0/{item_id}")
-def get_path_param_gt0(item_id: float = Path(..., gt=0)):
+def get_path_param_gt0(item_id: float = Path(gt=0)):
     return item_id
 
 
 @app.get("/path/param-ge/{item_id}")
-def get_path_param_ge(item_id: float = Path(..., ge=3)):
+def get_path_param_ge(item_id: float = Path(ge=3)):
     return item_id
 
 
 @app.get("/path/param-lt/{item_id}")
-def get_path_param_lt(item_id: float = Path(..., lt=3)):
+def get_path_param_lt(item_id: float = Path(lt=3)):
     return item_id
 
 
 @app.get("/path/param-lt0/{item_id}")
-def get_path_param_lt0(item_id: float = Path(..., lt=0)):
+def get_path_param_lt0(item_id: float = Path(lt=0)):
     return item_id
 
 
 @app.get("/path/param-le/{item_id}")
-def get_path_param_le(item_id: float = Path(..., le=3)):
+def get_path_param_le(item_id: float = Path(le=3)):
     return item_id
 
 
 @app.get("/path/param-lt-gt/{item_id}")
-def get_path_param_lt_gt(item_id: float = Path(..., lt=3, gt=1)):
+def get_path_param_lt_gt(item_id: float = Path(lt=3, gt=1)):
     return item_id
 
 
 @app.get("/path/param-le-ge/{item_id}")
-def get_path_param_le_ge(item_id: float = Path(..., le=3, ge=1)):
+def get_path_param_le_ge(item_id: float = Path(le=3, ge=1)):
     return item_id
 
 
 @app.get("/path/param-lt-int/{item_id}")
-def get_path_param_lt_int(item_id: int = Path(..., lt=3)):
+def get_path_param_lt_int(item_id: int = Path(lt=3)):
     return item_id
 
 
 @app.get("/path/param-gt-int/{item_id}")
-def get_path_param_gt_int(item_id: int = Path(..., gt=3)):
+def get_path_param_gt_int(item_id: int = Path(gt=3)):
     return item_id
 
 
 @app.get("/path/param-le-int/{item_id}")
-def get_path_param_le_int(item_id: int = Path(..., le=3)):
+def get_path_param_le_int(item_id: int = Path(le=3)):
     return item_id
 
 
 @app.get("/path/param-ge-int/{item_id}")
-def get_path_param_ge_int(item_id: int = Path(..., ge=3)):
+def get_path_param_ge_int(item_id: int = Path(ge=3)):
     return item_id
 
 
 @app.get("/path/param-lt-gt-int/{item_id}")
-def get_path_param_lt_gt_int(item_id: int = Path(..., lt=3, gt=1)):
+def get_path_param_lt_gt_int(item_id: int = Path(lt=3, gt=1)):
     return item_id
 
 
 @app.get("/path/param-le-ge-int/{item_id}")
-def get_path_param_le_ge_int(item_id: int = Path(..., le=3, ge=1)):
+def get_path_param_le_ge_int(item_id: int = Path(le=3, ge=1)):
     return item_id
 
 
@@ -173,19 +173,19 @@ def get_query_type_int_default(query: int = 10):
 
 
 @app.get("/query/param")
-def get_query_param(query=Query(None)):
+def get_query_param(query=Query(default=None)):
     if query is None:
         return "foo bar"
     return f"foo bar {query}"
 
 
 @app.get("/query/param-required")
-def get_query_param_required(query=Query(...)):
+def get_query_param_required(query=Query()):
     return f"foo bar {query}"
 
 
 @app.get("/query/param-required/int")
-def get_query_param_required_type(query: int = Query(...)):
+def get_query_param_required_type(query: int = Query()):
     return f"foo bar {query}"
 
 
index 49a19f460cc043c6c83b6c6b3a14c523b851297d..23c366d5d7a6fdb208d1e03c6ad91cdc60a535a8 100644 (file)
@@ -26,14 +26,14 @@ async def get_database():
 
 @app.put("/invalid-user/{user_id}")
 def put_invalid_user(
-    user_id: str, name: str = Body(...), db: dict = Depends(get_database)
+    user_id: str, name: str = Body(), db: dict = Depends(get_database)
 ):
     db[user_id] = name
     raise HTTPException(status_code=400, detail="Invalid user")
 
 
 @app.put("/user/{user_id}")
-def put_user(user_id: str, name: str = Body(...), db: dict = Depends(get_database)):
+def put_user(user_id: str, name: str = Body(), db: dict = Depends(get_database)):
     db[user_id] = name
     return {"message": "OK"}
 
index be917eab7e2e085561b094d646d27a61ae344c9e..52ce247533eb18bf48f96f2c11d882d2a55fe279 100644 (file)
@@ -5,17 +5,17 @@ app = FastAPI()
 
 
 @app.post("/form/python-list")
-def post_form_param_list(items: list = Form(...)):
+def post_form_param_list(items: list = Form()):
     return items
 
 
 @app.post("/form/python-set")
-def post_form_param_set(items: set = Form(...)):
+def post_form_param_set(items: set = Form()):
     return items
 
 
 @app.post("/form/python-tuple")
-def post_form_param_tuple(items: tuple = Form(...)):
+def post_form_param_tuple(items: tuple = Form()):
     return items
 
 
index f00dd7b9343c198db7c312ea1c8bc43421adba49..475786adbf80dfc5c03234662eabdc60d30fac83 100644 (file)
@@ -13,7 +13,7 @@ def test_invalid_sequence():
             title: str
 
         @app.get("/items/")
-        def read_items(q: List[Item] = Query(None)):
+        def read_items(q: List[Item] = Query(default=None)):
             pass  # pragma: no cover
 
 
@@ -25,7 +25,7 @@ def test_invalid_tuple():
             title: str
 
         @app.get("/items/")
-        def read_items(q: Tuple[Item, Item] = Query(None)):
+        def read_items(q: Tuple[Item, Item] = Query(default=None)):
             pass  # pragma: no cover
 
 
@@ -37,7 +37,7 @@ def test_invalid_dict():
             title: str
 
         @app.get("/items/")
-        def read_items(q: Dict[str, Item] = Query(None)):
+        def read_items(q: Dict[str, Item] = Query(default=None)):
             pass  # pragma: no cover
 
 
@@ -49,5 +49,5 @@ def test_invalid_simple_dict():
             title: str
 
         @app.get("/items/")
-        def read_items(q: Optional[dict] = Query(None)):
+        def read_items(q: Optional[dict] = Query(default=None)):
             pass  # pragma: no cover
index fa82b5ea8358575e27e7909cdacdf1669867a00e..ed35fd32e43f0015e2b0448e9633fc587f8faaae 100644 (file)
@@ -67,7 +67,7 @@ class ModelWithConfig(BaseModel):
 
 
 class ModelWithAlias(BaseModel):
-    foo: str = Field(..., alias="Foo")
+    foo: str = Field(alias="Foo")
 
 
 class ModelWithDefault(BaseModel):
index 3c86c1865e74f09ec1b677e9898403b5e12ce298..37723689062cfb415356ccb1c9ba3b8e4ccb64c9 100644 (file)
@@ -4,5 +4,5 @@ router = APIRouter()
 
 
 @router.post("/compute")
-def compute(a: int = Body(...), b: str = Body(...)):
+def compute(a: int = Body(), b: str = Body()):
     return {"a": a, "b": b}
index f7c7fdfc690d1aa43bf49cce89f53638423bc9ae..b62118f84142c3b2ad4be6e690f7ab948b3adb25 100644 (file)
@@ -4,5 +4,5 @@ router = APIRouter()
 
 
 @router.post("/compute/")
-def compute(a: int = Body(...), b: str = Body(...)):
+def compute(a: int = Body(), b: str = Body()):
     return {"a": a, "b": b}
index 0a15833fa0ee967ba7fc89292508bf0735d0e90b..3da461af5a532c7c0514f13ef2388ecf3d384fd5 100644 (file)
@@ -7,7 +7,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-def read_items(q: List[int] = Query(None)):
+def read_items(q: List[int] = Query(default=None)):
     return {"q": q}
 
 
index c8a6fd942fa1ac2780fe73630dd40190c8ed9226..788d9ef5afd30e4d289654a1cd4972c93462fcda 100644 (file)
@@ -12,7 +12,7 @@ def test_incorrect_multipart_installed_form(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...)):
+        async def root(username: str = Form()):
             return username  # pragma: nocover
 
 
@@ -22,7 +22,7 @@ def test_incorrect_multipart_installed_file_upload(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(f: UploadFile = File(...)):
+        async def root(f: UploadFile = File()):
             return f  # pragma: nocover
 
 
@@ -32,7 +32,7 @@ def test_incorrect_multipart_installed_file_bytes(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(f: bytes = File(...)):
+        async def root(f: bytes = File()):
             return f  # pragma: nocover
 
 
@@ -42,7 +42,7 @@ def test_incorrect_multipart_installed_multi_form(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...), password: str = Form(...)):
+        async def root(username: str = Form(), password: str = Form()):
             return username  # pragma: nocover
 
 
@@ -52,7 +52,7 @@ def test_incorrect_multipart_installed_form_file(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...), f: UploadFile = File(...)):
+        async def root(username: str = Form(), f: UploadFile = File()):
             return username  # pragma: nocover
 
 
@@ -62,7 +62,7 @@ def test_no_multipart_installed(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...)):
+        async def root(username: str = Form()):
             return username  # pragma: nocover
 
 
@@ -72,7 +72,7 @@ def test_no_multipart_installed_file(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(f: UploadFile = File(...)):
+        async def root(f: UploadFile = File()):
             return f  # pragma: nocover
 
 
@@ -82,7 +82,7 @@ def test_no_multipart_installed_file_bytes(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(f: bytes = File(...)):
+        async def root(f: bytes = File()):
             return f  # pragma: nocover
 
 
@@ -92,7 +92,7 @@ def test_no_multipart_installed_multi_form(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...), password: str = Form(...)):
+        async def root(username: str = Form(), password: str = Form()):
             return username  # pragma: nocover
 
 
@@ -102,5 +102,5 @@ def test_no_multipart_installed_form_file(monkeypatch):
         app = FastAPI()
 
         @app.post("/")
-        async def root(username: str = Form(...), f: UploadFile = File(...)):
+        async def root(username: str = Form(), f: UploadFile = File()):
             return username  # pragma: nocover
index f5767ec96cab892f9edcb95c38cf8d00f99b87cc..1fd40dcd218b903281b4ca94d9344aa65ec56d7f 100644 (file)
@@ -8,7 +8,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-def read_items(q: Optional[str] = Param(None)):  # type: ignore
+def read_items(q: Optional[str] = Param(default=None)):  # type: ignore
     return {"q": q}
 
 
index 26aa6389716447f140b8a5b4f7f0ce3693ca8524..214f039b67d3ea4390b508f89c720fb050eae78e 100644 (file)
@@ -9,26 +9,26 @@ app = FastAPI()
 
 @app.get("/hidden_cookie")
 async def hidden_cookie(
-    hidden_cookie: Optional[str] = Cookie(None, include_in_schema=False)
+    hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False)
 ):
     return {"hidden_cookie": hidden_cookie}
 
 
 @app.get("/hidden_header")
 async def hidden_header(
-    hidden_header: Optional[str] = Header(None, include_in_schema=False)
+    hidden_header: Optional[str] = Header(default=None, include_in_schema=False)
 ):
     return {"hidden_header": hidden_header}
 
 
 @app.get("/hidden_path/{hidden_path}")
-async def hidden_path(hidden_path: str = Path(..., include_in_schema=False)):
+async def hidden_path(hidden_path: str = Path(include_in_schema=False)):
     return {"hidden_path": hidden_path}
 
 
 @app.get("/hidden_query")
 async def hidden_query(
-    hidden_query: Optional[str] = Query(None, include_in_schema=False)
+    hidden_query: Optional[str] = Query(default=None, include_in_schema=False)
 ):
     return {"hidden_query": hidden_query}
 
index 00441694ee18a6a4b22f3e241a899136b53b54d9..ca0305184aaff190b08e67fa932cf67990a56a2c 100644 (file)
@@ -4,7 +4,7 @@ from fastapi.testclient import TestClient
 app = FastAPI()
 
 
-def get_header(*, someheader: str = Header(...)):
+def get_header(*, someheader: str = Header()):
     return someheader
 
 
index ace6bdef76ee6a1f8a5a188a6a96afaef23c3e94..e9cf4006d9effb0fb33c1fa69350237792dec35f 100644 (file)
@@ -21,14 +21,14 @@ class Shop(BaseModel):
 
 
 @app.post("/products")
-async def create_product(data: Product = Body(..., media_type=media_type, embed=True)):
+async def create_product(data: Product = Body(media_type=media_type, embed=True)):
     pass  # pragma: no cover
 
 
 @app.post("/shops")
 async def create_shop(
-    data: Shop = Body(..., media_type=media_type),
-    included: typing.List[Product] = Body([], media_type=media_type),
+    data: Shop = Body(media_type=media_type),
+    included: typing.List[Product] = Body(default=[], media_type=media_type),
 ):
     pass  # pragma: no cover
 
index 444e350a86a165be35e82b5ab4458dbb80e8af42..5047aeaa4b02ae05a9a6daa6d17072f3d3b1b11b 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Union
+
 from fastapi import Body, Cookie, FastAPI, Header, Path, Query
 from fastapi.testclient import TestClient
 from pydantic import BaseModel
@@ -18,14 +20,13 @@ def schema_extra(item: Item):
 
 
 @app.post("/example/")
-def example(item: Item = Body(..., example={"data": "Data in Body example"})):
+def example(item: Item = Body(example={"data": "Data in Body example"})):
     return item
 
 
 @app.post("/examples/")
 def examples(
     item: Item = Body(
-        ...,
         examples={
             "example1": {
                 "summary": "example1 summary",
@@ -41,7 +42,6 @@ def examples(
 @app.post("/example_examples/")
 def example_examples(
     item: Item = Body(
-        ...,
         example={"data": "Overriden example"},
         examples={
             "example1": {"value": {"data": "examples example_examples 1"}},
@@ -55,7 +55,7 @@ def example_examples(
 # TODO: enable these tests once/if Form(embed=False) is supported
 # TODO: In that case, define if File() should support example/examples too
 # @app.post("/form_example")
-# def form_example(firstname: str = Form(..., example="John")):
+# def form_example(firstname: str = Form(example="John")):
 #     return firstname
 
 
@@ -89,7 +89,6 @@ def example_examples(
 @app.get("/path_example/{item_id}")
 def path_example(
     item_id: str = Path(
-        ...,
         example="item_1",
     ),
 ):
@@ -99,7 +98,6 @@ def path_example(
 @app.get("/path_examples/{item_id}")
 def path_examples(
     item_id: str = Path(
-        ...,
         examples={
             "example1": {"summary": "item ID summary", "value": "item_1"},
             "example2": {"value": "item_2"},
@@ -112,7 +110,6 @@ def path_examples(
 @app.get("/path_example_examples/{item_id}")
 def path_example_examples(
     item_id: str = Path(
-        ...,
         example="item_overriden",
         examples={
             "example1": {"summary": "item ID summary", "value": "item_1"},
@@ -125,8 +122,8 @@ def path_example_examples(
 
 @app.get("/query_example/")
 def query_example(
-    data: str = Query(
-        None,
+    data: Union[str, None] = Query(
+        default=None,
         example="query1",
     ),
 ):
@@ -135,8 +132,8 @@ def query_example(
 
 @app.get("/query_examples/")
 def query_examples(
-    data: str = Query(
-        None,
+    data: Union[str, None] = Query(
+        default=None,
         examples={
             "example1": {"summary": "Query example 1", "value": "query1"},
             "example2": {"value": "query2"},
@@ -148,8 +145,8 @@ def query_examples(
 
 @app.get("/query_example_examples/")
 def query_example_examples(
-    data: str = Query(
-        None,
+    data: Union[str, None] = Query(
+        default=None,
         example="query_overriden",
         examples={
             "example1": {"summary": "Qeury example 1", "value": "query1"},
@@ -162,8 +159,8 @@ def query_example_examples(
 
 @app.get("/header_example/")
 def header_example(
-    data: str = Header(
-        None,
+    data: Union[str, None] = Header(
+        default=None,
         example="header1",
     ),
 ):
@@ -172,8 +169,8 @@ def header_example(
 
 @app.get("/header_examples/")
 def header_examples(
-    data: str = Header(
-        None,
+    data: Union[str, None] = Header(
+        default=None,
         examples={
             "example1": {"summary": "header example 1", "value": "header1"},
             "example2": {"value": "header2"},
@@ -185,8 +182,8 @@ def header_examples(
 
 @app.get("/header_example_examples/")
 def header_example_examples(
-    data: str = Header(
-        None,
+    data: Union[str, None] = Header(
+        default=None,
         example="header_overriden",
         examples={
             "example1": {"summary": "Qeury example 1", "value": "header1"},
@@ -199,8 +196,8 @@ def header_example_examples(
 
 @app.get("/cookie_example/")
 def cookie_example(
-    data: str = Cookie(
-        None,
+    data: Union[str, None] = Cookie(
+        default=None,
         example="cookie1",
     ),
 ):
@@ -209,8 +206,8 @@ def cookie_example(
 
 @app.get("/cookie_examples/")
 def cookie_examples(
-    data: str = Cookie(
-        None,
+    data: Union[str, None] = Cookie(
+        default=None,
         examples={
             "example1": {"summary": "cookie example 1", "value": "cookie1"},
             "example2": {"value": "cookie2"},
@@ -222,8 +219,8 @@ def cookie_examples(
 
 @app.get("/cookie_example_examples/")
 def cookie_example_examples(
-    data: str = Cookie(
-        None,
+    data: Union[str, None] = Cookie(
+        default=None,
         example="cookie_overriden",
         examples={
             "example1": {"summary": "Qeury example 1", "value": "cookie1"},
index 2956674376a5802a5f2ecb62d7f7bdef75a122e3..3bb46b2e9bcd6d08f08d82f81d3612fe66f6fb9e 100644 (file)
@@ -8,7 +8,7 @@ app = FastAPI()
 
 
 class Item(BaseModel):
-    name: str = Field(..., alias="aliased_name")
+    name: str = Field(alias="aliased_name")
     price: Optional[float] = None
     owner_ids: Optional[List[int]] = None
 
index 2320c7005f2cb38de8e1a3da3da3c7da5ad15610..5a980cbf6dad7d73bd8fdcda55705d129d632b2e 100644 (file)
@@ -5,17 +5,17 @@ app = FastAPI()
 
 
 @app.get("/int/{param:int}")
-def int_convertor(param: int = Path(...)):
+def int_convertor(param: int = Path()):
     return {"int": param}
 
 
 @app.get("/float/{param:float}")
-def float_convertor(param: float = Path(...)):
+def float_convertor(param: float = Path()):
     return {"float": param}
 
 
 @app.get("/path/{param:path}")
-def path_convertor(param: str = Path(...)):
+def path_convertor(param: str = Path()):
     return {"path": param}
 
 
index 2085dc3670eed40d54be27a22af6ef67dc17b25f..18ec2d04899121b9089c91201f0a16bbaa9d05e0 100644 (file)
@@ -27,7 +27,7 @@ def post_tuple_of_models(square: Tuple[Coordinate, Coordinate]):
 
 
 @app.post("/tuple-form/")
-def hello(values: Tuple[int, int] = Form(...)):
+def hello(values: Tuple[int, int] = Form()):
     return values