From d0573f5713b0a8ce2dbb3d12d36a7fc34b89e2ff Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Sat, 7 Jan 2023 15:45:48 +0200 Subject: [PATCH 01/34] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20functio?= =?UTF-8?q?n=20return=20type=20annotations=20to=20declare=20the=20`respons?= =?UTF-8?q?e=5Fmodel`=20(#1436)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/en/docs/tutorial/response-model.md | 142 ++- docs_src/response_model/tutorial001.py | 12 +- docs_src/response_model/tutorial001_01.py | 27 + .../response_model/tutorial001_01_py310.py | 25 + .../response_model/tutorial001_01_py39.py | 27 + docs_src/response_model/tutorial001_py310.py | 12 +- docs_src/response_model/tutorial001_py39.py | 12 +- docs_src/response_model/tutorial002.py | 4 +- docs_src/response_model/tutorial002_py310.py | 4 +- docs_src/response_model/tutorial003.py | 4 +- docs_src/response_model/tutorial003_01.py | 21 + .../response_model/tutorial003_01_py310.py | 19 + docs_src/response_model/tutorial003_py310.py | 4 +- fastapi/applications.py | 20 +- fastapi/dependencies/utils.py | 16 +- fastapi/routing.py | 25 +- tests/test_reponse_set_reponse_code_empty.py | 1 + ...est_response_model_as_return_annotation.py | 1051 +++++++++++++++++ 18 files changed, 1368 insertions(+), 58 deletions(-) create mode 100644 docs_src/response_model/tutorial001_01.py create mode 100644 docs_src/response_model/tutorial001_01_py310.py create mode 100644 docs_src/response_model/tutorial001_01_py39.py create mode 100644 docs_src/response_model/tutorial003_01.py create mode 100644 docs_src/response_model/tutorial003_01_py310.py create mode 100644 tests/test_response_model_as_return_annotation.py diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md index ab68314e8..69c02052d 100644 --- a/docs/en/docs/tutorial/response-model.md +++ b/docs/en/docs/tutorial/response-model.md @@ -1,6 +1,51 @@ -# Response Model +# Response Model - Return Type -You can declare the model used for the response with the parameter `response_model` in any of the *path operations*: +You can declare the type used for the response by annotating the *path operation function* **return type**. + +You can use **type annotations** the same way you would for input data in function **parameters**, you can use Pydantic models, lists, dictionaries, scalar values like integers, booleans, etc. + +=== "Python 3.6 and above" + + ```Python hl_lines="18 23" + {!> ../../../docs_src/response_model/tutorial001_01.py!} + ``` + +=== "Python 3.9 and above" + + ```Python hl_lines="18 23" + {!> ../../../docs_src/response_model/tutorial001_01_py39.py!} + ``` + +=== "Python 3.10 and above" + + ```Python hl_lines="16 21" + {!> ../../../docs_src/response_model/tutorial001_01_py310.py!} + ``` + +FastAPI will use this return type to: + +* **Validate** the returned data. + * If the data is invalid (e.g. you are missing a field), it means that *your* app code is broken, not returning what it should, and it will return a server error instead of returning incorrect data. This way you and your clients can be certain that they will receive the data and the data shape expected. +* Add a **JSON Schema** for the response, in the OpenAPI *path operation*. + * This will be used by the **automatic docs**. + * It will also be used by automatic client code generation tools. + +But most importantly: + +* It will **limit and filter** the output data to what is defined in the return type. + * This is particularly important for **security**, we'll see more of that below. + +## `response_model` Parameter + +There are some cases where you need or want to return some data that is not exactly what the type declares. + +For example, you could want to **return a dictionary** or a database object, but **declare it as a Pydantic model**. This way the Pydantic model would do all the data documentation, validation, etc. for the object that you returned (e.g. a dictionary or database object). + +If you added the return type annotation, tools and editors would complain with a (correct) error telling you that your function is returning a type (e.g. a dict) that is different from what you declared (e.g. a Pydantic model). + +In those cases, you can use the *path operation decorator* parameter `response_model` instead of the return type. + +You can use the `response_model` parameter in any of the *path operations*: * `@app.get()` * `@app.post()` @@ -10,40 +55,39 @@ You can declare the model used for the response with the parameter `response_mod === "Python 3.6 and above" - ```Python hl_lines="17" + ```Python hl_lines="17 22 24-27" {!> ../../../docs_src/response_model/tutorial001.py!} ``` === "Python 3.9 and above" - ```Python hl_lines="17" + ```Python hl_lines="17 22 24-27" {!> ../../../docs_src/response_model/tutorial001_py39.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="15" + ```Python hl_lines="17 22 24-27" {!> ../../../docs_src/response_model/tutorial001_py310.py!} ``` !!! note Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body. -It receives the same type you would declare for a Pydantic model attribute, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`. +`response_model` receives the same type you would declare for a Pydantic model field, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`. + +FastAPI will use this `response_model` to do all the data documentation, validation, etc. and also to **convert and filter the output data** to its type declaration. -FastAPI will use this `response_model` to: +!!! tip + If you have strict type checks in your editor, mypy, etc, you can declare the function return type as `Any`. -* Convert the output data to its type declaration. -* Validate the data. -* Add a JSON Schema for the response, in the OpenAPI *path operation*. -* Will be used by the automatic documentation systems. + That way you tell the editor that you are intentionally returning anything. But FastAPI will still do the data documentation, validation, filtering, etc. with the `response_model`. -But most importantly: +### `response_model` Priority -* Will limit the output data to that of the model. We'll see how that's important below. +If you declare both a return type and a `response_model`, the `response_model` will take priority and be used by FastAPI. -!!! note "Technical Details" - The response model is declared in this parameter instead of as a function return type annotation, because the path function may not actually return that response model but rather return a `dict`, database object or some other model, and then use the `response_model` to perform the field limiting and serialization. +This way you can add correct type annotations to your functions even when you are returning a type different than the response model, to be used by the editor and tools like mypy. And still you can have FastAPI do the data validation, documentation, etc. using the `response_model`. ## Return the same input data @@ -71,24 +115,24 @@ And we are using this model to declare our input and the same model to declare o === "Python 3.6 and above" - ```Python hl_lines="17-18" + ```Python hl_lines="18" {!> ../../../docs_src/response_model/tutorial002.py!} ``` === "Python 3.10 and above" - ```Python hl_lines="15-16" + ```Python hl_lines="16" {!> ../../../docs_src/response_model/tutorial002_py310.py!} ``` Now, whenever a browser is creating a user with a password, the API will return the same password in the response. -In this case, it might not be a problem, because the user themself is sending the password. +In this case, it might not be a problem, because it's the same user sending the password. But if we use the same model for another *path operation*, we could be sending our user's passwords to every client. !!! danger - Never store the plain password of a user or send it in a response. + Never store the plain password of a user or send it in a response like this, unless you know all the caveats and you know what you are doing. ## Add an output model @@ -102,7 +146,7 @@ We can instead create an input model with the plaintext password and an output m === "Python 3.10 and above" - ```Python hl_lines="7 9 14" + ```Python hl_lines="9 11 16" {!> ../../../docs_src/response_model/tutorial003_py310.py!} ``` @@ -116,7 +160,7 @@ Here, even though our *path operation function* is returning the same input user === "Python 3.10 and above" - ```Python hl_lines="22" + ```Python hl_lines="24" {!> ../../../docs_src/response_model/tutorial003_py310.py!} ``` @@ -130,12 +174,66 @@ Here, even though our *path operation function* is returning the same input user === "Python 3.10 and above" - ```Python hl_lines="20" + ```Python hl_lines="22" {!> ../../../docs_src/response_model/tutorial003_py310.py!} ``` So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic). +### `response_model` or Return Type + +In this case, because the two models are different, if we annotated the function return type as `UserOut`, the editor and tools would complain that we are returning an invalid type, as those are different classes. + +That's why in this example we have to declare it in the `response_model` parameter. + +...but continue reading below to see how to overcome that. + +## Return Type and Data Filtering + +Let's continue from the previous example. We wanted to **annotate the function with one type** but return something that includes **more data**. + +We want FastAPI to keep **filtering** the data using the response model. + +In the previous example, because the classes were different, we had to use the `response_model` parameter. But that also means that we don't get the support from the editor and tools checking the function return type. + +But in most of the cases where we need to do something like this, we want the model just to **filter/remove** some of the data as in this example. + +And in those cases, we can use classes and inheritance to take advantage of function **type annotations** to get better support in the editor and tools, and still get the FastAPI **data filtering**. + +=== "Python 3.6 and above" + + ```Python hl_lines="9-13 15-16 20" + {!> ../../../docs_src/response_model/tutorial003_01.py!} + ``` + +=== "Python 3.10 and above" + + ```Python hl_lines="7-10 13-14 18" + {!> ../../../docs_src/response_model/tutorial003_01_py310.py!} + ``` + +With this, we get tooling support, from editors and mypy as this code is correct in terms of types, but we also get the data filtering from FastAPI. + +How does this work? Let's check that out. 🤓 + +### Type Annotations and Tooling + +First let's see how editors, mypy and other tools would see this. + +`BaseUser` has the base fields. Then `UserIn` inherits from `BaseUser` and adds the `password` field, so, it will include all the fields from both models. + +We annotate the function return type as `BaseUser`, but we are actually returning a `UserIn` instance. + +The editor, mypy, and other tools won't complain about this because, in typing terms, `UserIn` is a subclass of `BaseUser`, which means it's a *valid* type when what is expected is anything that is a `BaseUser`. + +### FastAPI Data Filtering + +Now, for FastAPI, it will see the return type and make sure that what you return includes **only** the fields that are declared in the type. + +FastAPI does several things internally with Pydantic to make sure that those same rules of class inheritance are not used for the returned data filtering, otherwise you could end up returning much more data than what you expected. + +This way, you can get the best of both worlds: type annotations with **tooling support** and **data filtering**. + ## See it in the docs When you see the automatic docs, you can check that the input model and output model will both have their own JSON Schema: diff --git a/docs_src/response_model/tutorial001.py b/docs_src/response_model/tutorial001.py index 0f6e03e5b..fd1c902a5 100644 --- a/docs_src/response_model/tutorial001.py +++ b/docs_src/response_model/tutorial001.py @@ -1,4 +1,4 @@ -from typing import List, Union +from typing import Any, List, Union from fastapi import FastAPI from pydantic import BaseModel @@ -15,5 +15,13 @@ class Item(BaseModel): @app.post("/items/", response_model=Item) -async def create_item(item: Item): +async def create_item(item: Item) -> Any: return item + + +@app.get("/items/", response_model=List[Item]) +async def read_items() -> Any: + return [ + {"name": "Portal Gun", "price": 42.0}, + {"name": "Plumbus", "price": 32.0}, + ] diff --git a/docs_src/response_model/tutorial001_01.py b/docs_src/response_model/tutorial001_01.py new file mode 100644 index 000000000..98d30d540 --- /dev/null +++ b/docs_src/response_model/tutorial001_01.py @@ -0,0 +1,27 @@ +from typing import List, Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: Union[str, None] = None + price: float + tax: Union[float, None] = None + tags: List[str] = [] + + +@app.post("/items/") +async def create_item(item: Item) -> Item: + return item + + +@app.get("/items/") +async def read_items() -> List[Item]: + return [ + Item(name="Portal Gun", price=42.0), + Item(name="Plumbus", price=32.0), + ] diff --git a/docs_src/response_model/tutorial001_01_py310.py b/docs_src/response_model/tutorial001_01_py310.py new file mode 100644 index 000000000..7951c1076 --- /dev/null +++ b/docs_src/response_model/tutorial001_01_py310.py @@ -0,0 +1,25 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + price: float + tax: float | None = None + tags: list[str] = [] + + +@app.post("/items/") +async def create_item(item: Item) -> Item: + return item + + +@app.get("/items/") +async def read_items() -> list[Item]: + return [ + Item(name="Portal Gun", price=42.0), + Item(name="Plumbus", price=32.0), + ] diff --git a/docs_src/response_model/tutorial001_01_py39.py b/docs_src/response_model/tutorial001_01_py39.py new file mode 100644 index 000000000..16c78aa3f --- /dev/null +++ b/docs_src/response_model/tutorial001_01_py39.py @@ -0,0 +1,27 @@ +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: Union[str, None] = None + price: float + tax: Union[float, None] = None + tags: list[str] = [] + + +@app.post("/items/") +async def create_item(item: Item) -> Item: + return item + + +@app.get("/items/") +async def read_items() -> list[Item]: + return [ + Item(name="Portal Gun", price=42.0), + Item(name="Plumbus", price=32.0), + ] diff --git a/docs_src/response_model/tutorial001_py310.py b/docs_src/response_model/tutorial001_py310.py index 59efecde4..f8a2aa9fc 100644 --- a/docs_src/response_model/tutorial001_py310.py +++ b/docs_src/response_model/tutorial001_py310.py @@ -1,3 +1,5 @@ +from typing import Any + from fastapi import FastAPI from pydantic import BaseModel @@ -13,5 +15,13 @@ class Item(BaseModel): @app.post("/items/", response_model=Item) -async def create_item(item: Item): +async def create_item(item: Item) -> Any: return item + + +@app.get("/items/", response_model=list[Item]) +async def read_items() -> Any: + return [ + {"name": "Portal Gun", "price": 42.0}, + {"name": "Plumbus", "price": 32.0}, + ] diff --git a/docs_src/response_model/tutorial001_py39.py b/docs_src/response_model/tutorial001_py39.py index cdcca39d2..261e252d0 100644 --- a/docs_src/response_model/tutorial001_py39.py +++ b/docs_src/response_model/tutorial001_py39.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Any, Union from fastapi import FastAPI from pydantic import BaseModel @@ -15,5 +15,13 @@ class Item(BaseModel): @app.post("/items/", response_model=Item) -async def create_item(item: Item): +async def create_item(item: Item) -> Any: return item + + +@app.get("/items/", response_model=list[Item]) +async def read_items() -> Any: + return [ + {"name": "Portal Gun", "price": 42.0}, + {"name": "Plumbus", "price": 32.0}, + ] diff --git a/docs_src/response_model/tutorial002.py b/docs_src/response_model/tutorial002.py index c68e8b138..a58668f9e 100644 --- a/docs_src/response_model/tutorial002.py +++ b/docs_src/response_model/tutorial002.py @@ -14,6 +14,6 @@ class UserIn(BaseModel): # Don't do this in production! -@app.post("/user/", response_model=UserIn) -async def create_user(user: UserIn): +@app.post("/user/") +async def create_user(user: UserIn) -> UserIn: return user diff --git a/docs_src/response_model/tutorial002_py310.py b/docs_src/response_model/tutorial002_py310.py index 29ab9c9d2..0a91a5967 100644 --- a/docs_src/response_model/tutorial002_py310.py +++ b/docs_src/response_model/tutorial002_py310.py @@ -12,6 +12,6 @@ class UserIn(BaseModel): # Don't do this in production! -@app.post("/user/", response_model=UserIn) -async def create_user(user: UserIn): +@app.post("/user/") +async def create_user(user: UserIn) -> UserIn: return user diff --git a/docs_src/response_model/tutorial003.py b/docs_src/response_model/tutorial003.py index 37e493dcb..c42dbc707 100644 --- a/docs_src/response_model/tutorial003.py +++ b/docs_src/response_model/tutorial003.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Any, Union from fastapi import FastAPI from pydantic import BaseModel, EmailStr @@ -20,5 +20,5 @@ class UserOut(BaseModel): @app.post("/user/", response_model=UserOut) -async def create_user(user: UserIn): +async def create_user(user: UserIn) -> Any: return user diff --git a/docs_src/response_model/tutorial003_01.py b/docs_src/response_model/tutorial003_01.py new file mode 100644 index 000000000..52694b551 --- /dev/null +++ b/docs_src/response_model/tutorial003_01.py @@ -0,0 +1,21 @@ +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel, EmailStr + +app = FastAPI() + + +class BaseUser(BaseModel): + username: str + email: EmailStr + full_name: Union[str, None] = None + + +class UserIn(BaseUser): + password: str + + +@app.post("/user/") +async def create_user(user: UserIn) -> BaseUser: + return user diff --git a/docs_src/response_model/tutorial003_01_py310.py b/docs_src/response_model/tutorial003_01_py310.py new file mode 100644 index 000000000..6ffddfd0a --- /dev/null +++ b/docs_src/response_model/tutorial003_01_py310.py @@ -0,0 +1,19 @@ +from fastapi import FastAPI +from pydantic import BaseModel, EmailStr + +app = FastAPI() + + +class BaseUser(BaseModel): + username: str + email: EmailStr + full_name: str | None = None + + +class UserIn(BaseUser): + password: str + + +@app.post("/user/") +async def create_user(user: UserIn) -> BaseUser: + return user diff --git a/docs_src/response_model/tutorial003_py310.py b/docs_src/response_model/tutorial003_py310.py index fc9693e3c..3703bf888 100644 --- a/docs_src/response_model/tutorial003_py310.py +++ b/docs_src/response_model/tutorial003_py310.py @@ -1,3 +1,5 @@ +from typing import Any + from fastapi import FastAPI from pydantic import BaseModel, EmailStr @@ -18,5 +20,5 @@ class UserOut(BaseModel): @app.post("/user/", response_model=UserOut) -async def create_user(user: UserIn): +async def create_user(user: UserIn) -> Any: return user diff --git a/fastapi/applications.py b/fastapi/applications.py index 61d4582d2..36dc2605d 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -274,7 +274,7 @@ class FastAPI(Starlette): path: str, endpoint: Callable[..., Coroutine[Any, Any, Response]], *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -332,7 +332,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -435,7 +435,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -490,7 +490,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -545,7 +545,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -600,7 +600,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -655,7 +655,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -710,7 +710,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -765,7 +765,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, @@ -820,7 +820,7 @@ class FastAPI(Starlette): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[Depends]] = None, diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 4c817d5d0..32e171f18 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -253,7 +253,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: name=param.name, kind=param.kind, default=param.default, - annotation=get_typed_annotation(param, globalns), + annotation=get_typed_annotation(param.annotation, globalns), ) for param in signature.parameters.values() ] @@ -261,14 +261,24 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: return typed_signature -def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any: - annotation = param.annotation +def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) annotation = evaluate_forwardref(annotation, globalns, globalns) return annotation +def get_typed_return_annotation(call: Callable[..., Any]) -> Any: + signature = inspect.signature(call) + annotation = signature.return_annotation + + if annotation is inspect.Signature.empty: + return None + + globalns = getattr(call, "__globals__", {}) + return get_typed_annotation(annotation, globalns) + + def get_dependant( *, path: str, diff --git a/fastapi/routing.py b/fastapi/routing.py index 9a7d88efc..8c73b954f 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -26,6 +26,7 @@ from fastapi.dependencies.utils import ( get_body_field, get_dependant, get_parameterless_sub_dependant, + get_typed_return_annotation, solve_dependencies, ) from fastapi.encoders import DictIntStrAny, SetIntStr, jsonable_encoder @@ -323,7 +324,7 @@ class APIRoute(routing.Route): path: str, endpoint: Callable[..., Any], *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -354,6 +355,8 @@ class APIRoute(routing.Route): ) -> None: self.path = path self.endpoint = endpoint + if isinstance(response_model, DefaultPlaceholder): + response_model = get_typed_return_annotation(endpoint) self.response_model = response_model self.summary = summary self.response_description = response_description @@ -519,7 +522,7 @@ class APIRouter(routing.Router): path: str, endpoint: Callable[..., Any], *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -600,7 +603,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -795,7 +798,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -851,7 +854,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -907,7 +910,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -963,7 +966,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -1019,7 +1022,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -1075,7 +1078,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -1131,7 +1134,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, @@ -1187,7 +1190,7 @@ class APIRouter(routing.Router): self, path: str, *, - response_model: Any = None, + response_model: Any = Default(None), status_code: Optional[int] = None, tags: Optional[List[Union[str, Enum]]] = None, dependencies: Optional[Sequence[params.Depends]] = None, diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_reponse_set_reponse_code_empty.py index 094d54a84..50ec753a0 100644 --- a/tests/test_reponse_set_reponse_code_empty.py +++ b/tests/test_reponse_set_reponse_code_empty.py @@ -9,6 +9,7 @@ app = FastAPI() @app.delete( "/{id}", status_code=204, + response_model=None, ) async def delete_deployment( id: int, diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py new file mode 100644 index 000000000..f2056fecd --- /dev/null +++ b/tests/test_response_model_as_return_annotation.py @@ -0,0 +1,1051 @@ +from typing import List, Union + +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel, ValidationError + + +class BaseUser(BaseModel): + name: str + + +class User(BaseUser): + surname: str + + +class DBUser(User): + password_hash: str + + +class Item(BaseModel): + name: str + price: float + + +app = FastAPI() + + +@app.get("/no_response_model-no_annotation-return_model") +def no_response_model_no_annotation_return_model(): + return User(name="John", surname="Doe") + + +@app.get("/no_response_model-no_annotation-return_dict") +def no_response_model_no_annotation_return_dict(): + return {"name": "John", "surname": "Doe"} + + +@app.get("/response_model-no_annotation-return_same_model", response_model=User) +def response_model_no_annotation_return_same_model(): + return User(name="John", surname="Doe") + + +@app.get("/response_model-no_annotation-return_exact_dict", response_model=User) +def response_model_no_annotation_return_exact_dict(): + return {"name": "John", "surname": "Doe"} + + +@app.get("/response_model-no_annotation-return_invalid_dict", response_model=User) +def response_model_no_annotation_return_invalid_dict(): + return {"name": "John"} + + +@app.get("/response_model-no_annotation-return_invalid_model", response_model=User) +def response_model_no_annotation_return_invalid_model(): + return Item(name="Foo", price=42.0) + + +@app.get( + "/response_model-no_annotation-return_dict_with_extra_data", response_model=User +) +def response_model_no_annotation_return_dict_with_extra_data(): + return {"name": "John", "surname": "Doe", "password_hash": "secret"} + + +@app.get( + "/response_model-no_annotation-return_submodel_with_extra_data", response_model=User +) +def response_model_no_annotation_return_submodel_with_extra_data(): + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get("/no_response_model-annotation-return_same_model") +def no_response_model_annotation_return_same_model() -> User: + return User(name="John", surname="Doe") + + +@app.get("/no_response_model-annotation-return_exact_dict") +def no_response_model_annotation_return_exact_dict() -> User: + return {"name": "John", "surname": "Doe"} + + +@app.get("/no_response_model-annotation-return_invalid_dict") +def no_response_model_annotation_return_invalid_dict() -> User: + return {"name": "John"} + + +@app.get("/no_response_model-annotation-return_invalid_model") +def no_response_model_annotation_return_invalid_model() -> User: + return Item(name="Foo", price=42.0) + + +@app.get("/no_response_model-annotation-return_dict_with_extra_data") +def no_response_model_annotation_return_dict_with_extra_data() -> User: + return {"name": "John", "surname": "Doe", "password_hash": "secret"} + + +@app.get("/no_response_model-annotation-return_submodel_with_extra_data") +def no_response_model_annotation_return_submodel_with_extra_data() -> User: + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get("/response_model_none-annotation-return_same_model", response_model=None) +def response_model_none_annotation_return_same_model() -> User: + return User(name="John", surname="Doe") + + +@app.get("/response_model_none-annotation-return_exact_dict", response_model=None) +def response_model_none_annotation_return_exact_dict() -> User: + return {"name": "John", "surname": "Doe"} + + +@app.get("/response_model_none-annotation-return_invalid_dict", response_model=None) +def response_model_none_annotation_return_invalid_dict() -> User: + return {"name": "John"} + + +@app.get("/response_model_none-annotation-return_invalid_model", response_model=None) +def response_model_none_annotation_return_invalid_model() -> User: + return Item(name="Foo", price=42.0) + + +@app.get( + "/response_model_none-annotation-return_dict_with_extra_data", response_model=None +) +def response_model_none_annotation_return_dict_with_extra_data() -> User: + return {"name": "John", "surname": "Doe", "password_hash": "secret"} + + +@app.get( + "/response_model_none-annotation-return_submodel_with_extra_data", + response_model=None, +) +def response_model_none_annotation_return_submodel_with_extra_data() -> User: + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get( + "/response_model_model1-annotation_model2-return_same_model", response_model=User +) +def response_model_model1_annotation_model2_return_same_model() -> Item: + return User(name="John", surname="Doe") + + +@app.get( + "/response_model_model1-annotation_model2-return_exact_dict", response_model=User +) +def response_model_model1_annotation_model2_return_exact_dict() -> Item: + return {"name": "John", "surname": "Doe"} + + +@app.get( + "/response_model_model1-annotation_model2-return_invalid_dict", response_model=User +) +def response_model_model1_annotation_model2_return_invalid_dict() -> Item: + return {"name": "John"} + + +@app.get( + "/response_model_model1-annotation_model2-return_invalid_model", response_model=User +) +def response_model_model1_annotation_model2_return_invalid_model() -> Item: + return Item(name="Foo", price=42.0) + + +@app.get( + "/response_model_model1-annotation_model2-return_dict_with_extra_data", + response_model=User, +) +def response_model_model1_annotation_model2_return_dict_with_extra_data() -> Item: + return {"name": "John", "surname": "Doe", "password_hash": "secret"} + + +@app.get( + "/response_model_model1-annotation_model2-return_submodel_with_extra_data", + response_model=User, +) +def response_model_model1_annotation_model2_return_submodel_with_extra_data() -> Item: + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get( + "/response_model_filtering_model-annotation_submodel-return_submodel", + response_model=User, +) +def response_model_filtering_model_annotation_submodel_return_submodel() -> DBUser: + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get("/response_model_list_of_model-no_annotation", response_model=List[User]) +def response_model_list_of_model_no_annotation(): + return [ + DBUser(name="John", surname="Doe", password_hash="secret"), + DBUser(name="Jane", surname="Does", password_hash="secret2"), + ] + + +@app.get("/no_response_model-annotation_list_of_model") +def no_response_model_annotation_list_of_model() -> List[User]: + return [ + DBUser(name="John", surname="Doe", password_hash="secret"), + DBUser(name="Jane", surname="Does", password_hash="secret2"), + ] + + +@app.get("/no_response_model-annotation_forward_ref_list_of_model") +def no_response_model_annotation_forward_ref_list_of_model() -> "List[User]": + return [ + DBUser(name="John", surname="Doe", password_hash="secret"), + DBUser(name="Jane", surname="Does", password_hash="secret2"), + ] + + +@app.get( + "/response_model_union-no_annotation-return_model1", + response_model=Union[User, Item], +) +def response_model_union_no_annotation_return_model1(): + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get( + "/response_model_union-no_annotation-return_model2", + response_model=Union[User, Item], +) +def response_model_union_no_annotation_return_model2(): + return Item(name="Foo", price=42.0) + + +@app.get("/no_response_model-annotation_union-return_model1") +def no_response_model_annotation_union_return_model1() -> Union[User, Item]: + return DBUser(name="John", surname="Doe", password_hash="secret") + + +@app.get("/no_response_model-annotation_union-return_model2") +def no_response_model_annotation_union_return_model2() -> Union[User, Item]: + return Item(name="Foo", price=42.0) + + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/no_response_model-no_annotation-return_model": { + "get": { + "summary": "No Response Model No Annotation Return Model", + "operationId": "no_response_model_no_annotation_return_model_no_response_model_no_annotation_return_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/no_response_model-no_annotation-return_dict": { + "get": { + "summary": "No Response Model No Annotation Return Dict", + "operationId": "no_response_model_no_annotation_return_dict_no_response_model_no_annotation_return_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model-no_annotation-return_same_model": { + "get": { + "summary": "Response Model No Annotation Return Same Model", + "operationId": "response_model_no_annotation_return_same_model_response_model_no_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_exact_dict": { + "get": { + "summary": "Response Model No Annotation Return Exact Dict", + "operationId": "response_model_no_annotation_return_exact_dict_response_model_no_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_dict": { + "get": { + "summary": "Response Model No Annotation Return Invalid Dict", + "operationId": "response_model_no_annotation_return_invalid_dict_response_model_no_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_model": { + "get": { + "summary": "Response Model No Annotation Return Invalid Model", + "operationId": "response_model_no_annotation_return_invalid_model_response_model_no_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Dict With Extra Data", + "operationId": "response_model_no_annotation_return_dict_with_extra_data_response_model_no_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model-no_annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Submodel With Extra Data", + "operationId": "response_model_no_annotation_return_submodel_with_extra_data_response_model_no_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_same_model": { + "get": { + "summary": "No Response Model Annotation Return Same Model", + "operationId": "no_response_model_annotation_return_same_model_no_response_model_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_exact_dict": { + "get": { + "summary": "No Response Model Annotation Return Exact Dict", + "operationId": "no_response_model_annotation_return_exact_dict_no_response_model_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_dict": { + "get": { + "summary": "No Response Model Annotation Return Invalid Dict", + "operationId": "no_response_model_annotation_return_invalid_dict_no_response_model_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_model": { + "get": { + "summary": "No Response Model Annotation Return Invalid Model", + "operationId": "no_response_model_annotation_return_invalid_model_no_response_model_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_dict_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Dict With Extra Data", + "operationId": "no_response_model_annotation_return_dict_with_extra_data_no_response_model_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Submodel With Extra Data", + "operationId": "no_response_model_annotation_return_submodel_with_extra_data_no_response_model_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_none-annotation-return_same_model": { + "get": { + "summary": "Response Model None Annotation Return Same Model", + "operationId": "response_model_none_annotation_return_same_model_response_model_none_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_exact_dict": { + "get": { + "summary": "Response Model None Annotation Return Exact Dict", + "operationId": "response_model_none_annotation_return_exact_dict_response_model_none_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_dict": { + "get": { + "summary": "Response Model None Annotation Return Invalid Dict", + "operationId": "response_model_none_annotation_return_invalid_dict_response_model_none_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_model": { + "get": { + "summary": "Response Model None Annotation Return Invalid Model", + "operationId": "response_model_none_annotation_return_invalid_model_response_model_none_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Dict With Extra Data", + "operationId": "response_model_none_annotation_return_dict_with_extra_data_response_model_none_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Submodel With Extra Data", + "operationId": "response_model_none_annotation_return_submodel_with_extra_data_response_model_none_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_same_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Same Model", + "operationId": "response_model_model1_annotation_model2_return_same_model_response_model_model1_annotation_model2_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_exact_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Exact Dict", + "operationId": "response_model_model1_annotation_model2_return_exact_dict_response_model_model1_annotation_model2_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Dict", + "operationId": "response_model_model1_annotation_model2_return_invalid_dict_response_model_model1_annotation_model2_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Model", + "operationId": "response_model_model1_annotation_model2_return_invalid_model_response_model_model1_annotation_model2_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_dict_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Dict With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_dict_with_extra_data_response_model_model1_annotation_model2_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Submodel With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_submodel_with_extra_data_response_model_model1_annotation_model2_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_filtering_model-annotation_submodel-return_submodel": { + "get": { + "summary": "Response Model Filtering Model Annotation Submodel Return Submodel", + "operationId": "response_model_filtering_model_annotation_submodel_return_submodel_response_model_filtering_model_annotation_submodel_return_submodel_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_list_of_model-no_annotation": { + "get": { + "summary": "Response Model List Of Model No Annotation", + "operationId": "response_model_list_of_model_no_annotation_response_model_list_of_model_no_annotation_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model List Of Model No Annotation Response Model List Of Model No Annotation Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_list_of_model": { + "get": { + "summary": "No Response Model Annotation List Of Model", + "operationId": "no_response_model_annotation_list_of_model_no_response_model_annotation_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation List Of Model No Response Model Annotation List Of Model Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_forward_ref_list_of_model": { + "get": { + "summary": "No Response Model Annotation Forward Ref List Of Model", + "operationId": "no_response_model_annotation_forward_ref_list_of_model_no_response_model_annotation_forward_ref_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Forward Ref List Of Model No Response Model Annotation Forward Ref List Of Model Get", + "type": "array", + "items": {"$ref": "#/components/schemas/User"}, + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model1": { + "get": { + "summary": "Response Model Union No Annotation Return Model1", + "operationId": "response_model_union_no_annotation_return_model1_response_model_union_no_annotation_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model1 Response Model Union No Annotation Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model2": { + "get": { + "summary": "Response Model Union No Annotation Return Model2", + "operationId": "response_model_union_no_annotation_return_model2_response_model_union_no_annotation_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model2 Response Model Union No Annotation Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model1": { + "get": { + "summary": "No Response Model Annotation Union Return Model1", + "operationId": "no_response_model_annotation_union_return_model1_no_response_model_annotation_union_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model1 No Response Model Annotation Union Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model2": { + "get": { + "summary": "No Response Model Annotation Union Return Model2", + "operationId": "no_response_model_annotation_union_return_model2_no_response_model_annotation_union_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model2 No Response Model Annotation Union Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "User": { + "title": "User", + "required": ["name", "surname"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "surname": {"title": "Surname", "type": "string"}, + }, + }, + } + }, +} + + +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == openapi_schema + + +def test_no_response_model_no_annotation_return_model(): + response = client.get("/no_response_model-no_annotation-return_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_no_annotation_return_dict(): + response = client.get("/no_response_model-no_annotation-return_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_no_annotation_return_same_model(): + response = client.get("/response_model-no_annotation-return_same_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_no_annotation_return_exact_dict(): + response = client.get("/response_model-no_annotation-return_exact_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_no_annotation_return_invalid_dict(): + with pytest.raises(ValidationError): + client.get("/response_model-no_annotation-return_invalid_dict") + + +def test_response_model_no_annotation_return_invalid_model(): + with pytest.raises(ValidationError): + client.get("/response_model-no_annotation-return_invalid_model") + + +def test_response_model_no_annotation_return_dict_with_extra_data(): + response = client.get("/response_model-no_annotation-return_dict_with_extra_data") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_no_annotation_return_submodel_with_extra_data(): + response = client.get( + "/response_model-no_annotation-return_submodel_with_extra_data" + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_annotation_return_same_model(): + response = client.get("/no_response_model-annotation-return_same_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_annotation_return_exact_dict(): + response = client.get("/no_response_model-annotation-return_exact_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_annotation_return_invalid_dict(): + with pytest.raises(ValidationError): + client.get("/no_response_model-annotation-return_invalid_dict") + + +def test_no_response_model_annotation_return_invalid_model(): + with pytest.raises(ValidationError): + client.get("/no_response_model-annotation-return_invalid_model") + + +def test_no_response_model_annotation_return_dict_with_extra_data(): + response = client.get("/no_response_model-annotation-return_dict_with_extra_data") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_annotation_return_submodel_with_extra_data(): + response = client.get( + "/no_response_model-annotation-return_submodel_with_extra_data" + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_none_annotation_return_same_model(): + response = client.get("/response_model_none-annotation-return_same_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_none_annotation_return_exact_dict(): + response = client.get("/response_model_none-annotation-return_exact_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_none_annotation_return_invalid_dict(): + response = client.get("/response_model_none-annotation-return_invalid_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John"} + + +def test_response_model_none_annotation_return_invalid_model(): + response = client.get("/response_model_none-annotation-return_invalid_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "Foo", "price": 42.0} + + +def test_response_model_none_annotation_return_dict_with_extra_data(): + response = client.get("/response_model_none-annotation-return_dict_with_extra_data") + assert response.status_code == 200, response.text + assert response.json() == { + "name": "John", + "surname": "Doe", + "password_hash": "secret", + } + + +def test_response_model_none_annotation_return_submodel_with_extra_data(): + response = client.get( + "/response_model_none-annotation-return_submodel_with_extra_data" + ) + assert response.status_code == 200, response.text + assert response.json() == { + "name": "John", + "surname": "Doe", + "password_hash": "secret", + } + + +def test_response_model_model1_annotation_model2_return_same_model(): + response = client.get("/response_model_model1-annotation_model2-return_same_model") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_model1_annotation_model2_return_exact_dict(): + response = client.get("/response_model_model1-annotation_model2-return_exact_dict") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_model1_annotation_model2_return_invalid_dict(): + with pytest.raises(ValidationError): + client.get("/response_model_model1-annotation_model2-return_invalid_dict") + + +def test_response_model_model1_annotation_model2_return_invalid_model(): + with pytest.raises(ValidationError): + client.get("/response_model_model1-annotation_model2-return_invalid_model") + + +def test_response_model_model1_annotation_model2_return_dict_with_extra_data(): + response = client.get( + "/response_model_model1-annotation_model2-return_dict_with_extra_data" + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_model1_annotation_model2_return_submodel_with_extra_data(): + response = client.get( + "/response_model_model1-annotation_model2-return_submodel_with_extra_data" + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_filtering_model_annotation_submodel_return_submodel(): + response = client.get( + "/response_model_filtering_model-annotation_submodel-return_submodel" + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_list_of_model_no_annotation(): + response = client.get("/response_model_list_of_model-no_annotation") + assert response.status_code == 200, response.text + assert response.json() == [ + {"name": "John", "surname": "Doe"}, + {"name": "Jane", "surname": "Does"}, + ] + + +def test_no_response_model_annotation_list_of_model(): + response = client.get("/no_response_model-annotation_list_of_model") + assert response.status_code == 200, response.text + assert response.json() == [ + {"name": "John", "surname": "Doe"}, + {"name": "Jane", "surname": "Does"}, + ] + + +def test_no_response_model_annotation_forward_ref_list_of_model(): + response = client.get("/no_response_model-annotation_forward_ref_list_of_model") + assert response.status_code == 200, response.text + assert response.json() == [ + {"name": "John", "surname": "Doe"}, + {"name": "Jane", "surname": "Does"}, + ] + + +def test_response_model_union_no_annotation_return_model1(): + response = client.get("/response_model_union-no_annotation-return_model1") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_response_model_union_no_annotation_return_model2(): + response = client.get("/response_model_union-no_annotation-return_model2") + assert response.status_code == 200, response.text + assert response.json() == {"name": "Foo", "price": 42.0} + + +def test_no_response_model_annotation_union_return_model1(): + response = client.get("/no_response_model-annotation_union-return_model1") + assert response.status_code == 200, response.text + assert response.json() == {"name": "John", "surname": "Doe"} + + +def test_no_response_model_annotation_union_return_model2(): + response = client.get("/no_response_model-annotation_union-return_model2") + assert response.status_code == 200, response.text + assert response.json() == {"name": "Foo", "price": 42.0} From 18d087f9c66b06c8baa4164bdf647af362b4a4ee Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 13:46:24 +0000 Subject: [PATCH 02/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1d574906b..a0d1a7eb0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✨ Add support for function return type annotations to declare the `response_model`. PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). * ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo). From cb35e275e3f17badea3f3715a35b5e7028121eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Jan 2023 17:58:46 +0400 Subject: [PATCH 03/34] =?UTF-8?q?=F0=9F=94=A7=20Remove=20Doist=20sponsor?= =?UTF-8?q?=20(#5847)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/en/data/sponsors.yml | 3 --- docs/en/overrides/main.html | 6 ------ 3 files changed, 10 deletions(-) diff --git a/README.md b/README.md index 7c4a6c4b4..f3e60306e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 749f528c5..76128d69b 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -8,9 +8,6 @@ gold: - url: https://cryptapi.io/ title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway." img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg - - url: https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python - title: Help us migrate doist to FastAPI - img: https://fastapi.tiangolo.com/img/sponsors/doist.svg silver: - url: https://www.deta.sh/?ref=fastapi title: The launchpad for all your (team's) ideas diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index e9b9f60eb..b85f0c4cf 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -34,12 +34,6 @@ -
From 679aee85ce145fc9a9d052bffafd31d281ea6c58 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 13:59:26 +0000 Subject: [PATCH 04/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a0d1a7eb0..ed5369689 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). * ✨ Add support for function return type annotations to declare the `response_model`. PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). * ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot). From d70eef825e2a31cd0a7b37765c0b21514a336fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Jan 2023 18:13:34 +0400 Subject: [PATCH 05/34] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors,=20add?= =?UTF-8?q?=20Svix=20(#5848)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 + docs/en/docs/img/sponsors/svix.svg | 178 +++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 docs/en/docs/img/sponsors/svix.svg diff --git a/README.md b/README.md index f3e60306e..2b4de2a65 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 76128d69b..c39dbb589 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -30,6 +30,9 @@ silver: - url: https://careers.budget-insight.com/ title: Budget Insight is hiring! img: https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg + - url: https://www.svix.com/ + title: Svix - Webhooks as a service + img: https://fastapi.tiangolo.com/img/sponsors/svix.svg bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. diff --git a/docs/en/docs/img/sponsors/svix.svg b/docs/en/docs/img/sponsors/svix.svg new file mode 100644 index 000000000..845a860a2 --- /dev/null +++ b/docs/en/docs/img/sponsors/svix.svg @@ -0,0 +1,178 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a3edc760513f638a7dd417414787cfa23e2327e7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 14:14:07 +0000 Subject: [PATCH 06/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ed5369689..9cfce002b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). * ✨ Add support for function return type annotations to declare the `response_model`. PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). * ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot). From 2a3a786dd7dc8a9112a1f47dd1949d21be33284b Mon Sep 17 00:00:00 2001 From: Nina Hwang <79563565+NinaHwang@users.noreply.github.com> Date: Sat, 7 Jan 2023 23:21:23 +0900 Subject: [PATCH 07/34] =?UTF-8?q?=F0=9F=8C=90=20Add=20Korean=20translation?= =?UTF-8?q?=20for=20`docs/tutorial/cors.md`=20(#3764)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com> Co-authored-by: Sebastián Ramírez Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/ko/docs/tutorial/cors.md | 84 +++++++++++++++++++++++++++++++++++ docs/ko/mkdocs.yml | 1 + 2 files changed, 85 insertions(+) create mode 100644 docs/ko/docs/tutorial/cors.md diff --git a/docs/ko/docs/tutorial/cors.md b/docs/ko/docs/tutorial/cors.md new file mode 100644 index 000000000..39e9ea83f --- /dev/null +++ b/docs/ko/docs/tutorial/cors.md @@ -0,0 +1,84 @@ +# 교차 출처 리소스 공유 + +CORS 또는 "교차-출처 리소스 공유"란, 브라우저에서 동작하는 프론트엔드가 자바스크립트로 코드로 백엔드와 통신하고, 백엔드는 해당 프론트엔드와 다른 "출처"에 존재하는 상황을 의미합니다. + +## 출처 + +출처란 프로토콜(`http` , `https`), 도메인(`myapp.com`, `localhost`, `localhost.tiangolo.com` ), 그리고 포트(`80`, `443`, `8080` )의 조합을 의미합니다. + +따라서, 아래는 모두 상이한 출처입니다: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +모두 `localhost` 에 있지만, 서로 다른 프로토콜과 포트를 사용하고 있으므로 다른 "출처"입니다. + +## 단계 + +브라우저 내 `http://localhost:8080`에서 동작하는 프론트엔드가 있고, 자바스크립트는 `http://localhost`를 통해 백엔드와 통신한다고 가정해봅시다(포트를 명시하지 않는 경우, 브라우저는 `80` 을 기본 포트로 간주합니다). + +그러면 브라우저는 백엔드에 HTTP `OPTIONS` 요청을 보내고, 백엔드에서 이 다른 출처(`http://localhost:8080`)와의 통신을 허가하는 적절한 헤더를 보내면, 브라우저는 프론트엔드의 자바스크립트가 백엔드에 요청을 보낼 수 있도록 합니다. + +이를 위해, 백엔드는 "허용된 출처(allowed origins)" 목록을 가지고 있어야만 합니다. + +이 경우, 프론트엔드가 제대로 동작하기 위해 `http://localhost:8080`을 목록에 포함해야 합니다. + +## 와일드카드 + +모든 출처를 허용하기 위해 목록을 `"*"` ("와일드카드")로 선언하는 것도 가능합니다. + +하지만 이것은 특정한 유형의 통신만을 허용하며, 쿠키 및 액세스 토큰과 사용되는 인증 헤더(Authoriztion header) 등이 포함된 경우와 같이 자격 증명(credentials)이 포함된 통신은 허용되지 않습니다. + +따라서 모든 작업을 의도한대로 실행하기 위해, 허용되는 출처를 명시적으로 지정하는 것이 좋습니다. + +## `CORSMiddleware` 사용 + +`CORSMiddleware` 을 사용하여 **FastAPI** 응용 프로그램의 교차 출처 리소스 공유 환경을 설정할 수 있습니다. + +* `CORSMiddleware` 임포트. +* 허용되는 출처(문자열 형식)의 리스트 생성. +* FastAPI 응용 프로그램에 "미들웨어(middleware)"로 추가. + +백엔드에서 다음의 사항을 허용할지에 대해 설정할 수도 있습니다: + +* 자격증명 (인증 헤더, 쿠키 등). +* 특정한 HTTP 메소드(`POST`, `PUT`) 또는 와일드카드 `"*"` 를 사용한 모든 HTTP 메소드. +* 특정한 HTTP 헤더 또는 와일드카드 `"*"` 를 사용한 모든 HTTP 헤더. + +```Python hl_lines="2 6-11 13-19" +{!../../../docs_src/cors/tutorial001.py!} +``` + +`CORSMiddleware` 에서 사용하는 기본 매개변수는 제한적이므로, 브라우저가 교차-도메인 상황에서 특정한 출처, 메소드, 헤더 등을 사용할 수 있도록 하려면 이들을 명시적으로 허용해야 합니다. + +다음의 인자들이 지원됩니다: + +* `allow_origins` - 교차-출처 요청을 보낼 수 있는 출처의 리스트입니다. 예) `['https://example.org', 'https://www.example.org']`. 모든 출처를 허용하기 위해 `['*']` 를 사용할 수 있습니다. +* `allow_origin_regex` - 교차-출처 요청을 보낼 수 있는 출처를 정규표현식 문자열로 나타냅니다. `'https://.*\.example\.org'`. +* `allow_methods` - 교차-출처 요청을 허용하는 HTTP 메소드의 리스트입니다. 기본값은 `['GET']` 입니다. `['*']` 을 사용하여 모든 표준 메소드들을 허용할 수 있습니다. +* `allow_headers` - 교차-출처를 지원하는 HTTP 요청 헤더의 리스트입니다. 기본값은 `[]` 입니다. 모든 헤더들을 허용하기 위해 `['*']` 를 사용할 수 있습니다. `Accept`, `Accept-Language`, `Content-Language` 그리고 `Content-Type` 헤더는 CORS 요청시 언제나 허용됩니다. +* `allow_credentials` - 교차-출처 요청시 쿠키 지원 여부를 설정합니다. 기본값은 `False` 입니다. 또한 해당 항목을 허용할 경우 `allow_origins` 는 `['*']` 로 설정할 수 없으며, 출처를 반드시 특정해야 합니다. +* `expose_headers` - 브라우저에 접근할 수 있어야 하는 모든 응답 헤더를 가리킵니다. 기본값은 `[]` 입니다. +* `max_age` - 브라우저가 CORS 응답을 캐시에 저장하는 최대 시간을 초 단위로 설정합니다. 기본값은 `600` 입니다. + +미들웨어는 두가지 특정한 종류의 HTTP 요청에 응답합니다... + +### CORS 사전 요청 + +`Origin` 및 `Access-Control-Request-Method` 헤더와 함께 전송하는 모든 `OPTIONS` 요청입니다. + +이 경우 미들웨어는 들어오는 요청을 가로채 적절한 CORS 헤더와, 정보 제공을 위한 `200` 또는 `400` 응답으로 응답합니다. + +### 단순한 요청 + +`Origin` 헤더를 가진 모든 요청. 이 경우 미들웨어는 요청을 정상적으로 전달하지만, 적절한 CORS 헤더를 응답에 포함시킵니다. + +## 더 많은 정보 + +CORS에 대한 더 많은 정보를 알고싶다면, Mozilla CORS 문서를 참고하기 바랍니다. + +!!! note "기술적 세부 사항" + `from starlette.middleware.cors import CORSMiddleware` 역시 사용할 수 있습니다. + + **FastAPI**는 개발자인 당신의 편의를 위해 `fastapi.middleware` 에서 몇가지의 미들웨어를 제공합니다. 하지만 대부분의 미들웨어가 Stralette으로부터 직접 제공됩니다. diff --git a/docs/ko/mkdocs.yml b/docs/ko/mkdocs.yml index 50931e134..3dfc208c8 100644 --- a/docs/ko/mkdocs.yml +++ b/docs/ko/mkdocs.yml @@ -69,6 +69,7 @@ nav: - tutorial/request-files.md - tutorial/request-forms-and-files.md - tutorial/encoder.md + - tutorial/cors.md markdown_extensions: - toc: permalink: true From 1be95ba02dc907fb864d03c287c4851c35322515 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 14:21:59 +0000 Subject: [PATCH 08/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9cfce002b..02d2a088a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). * 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). * ✨ Add support for function return type annotations to declare the `response_model`. PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). From 3178c17776d7dfbe14a270c5128a483694a3477a Mon Sep 17 00:00:00 2001 From: Ben Ho <15027668g@gmail.com> Date: Sat, 7 Jan 2023 22:33:29 +0800 Subject: [PATCH 09/34] =?UTF-8?q?=F0=9F=8C=90=20Fix=20typo=20in=20Chinese?= =?UTF-8?q?=20translation=20for=20`docs/zh/docs/benchmarks.md`=20(#4269)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/zh/docs/benchmarks.md | 2 +- docs/zh/docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md index 8991c72cd..71e8d4838 100644 --- a/docs/zh/docs/benchmarks.md +++ b/docs/zh/docs/benchmarks.md @@ -1,6 +1,6 @@ # 基准测试 -第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 可用的最快的 Python 框架之一,仅次与 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。(*) +第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 可用的最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。(*) 但是在查看基准得分和对比时,请注意以下几点。 diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 7901e9c2c..4db3ef10c 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -28,7 +28,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框 关键特性: -* **快速**:可与 **NodeJS** 和 **Go** 比肩的极高性能(归功于 Starlette 和 Pydantic)。[最快的 Python web 框架之一](#_11)。 +* **快速**:可与 **NodeJS** 和 **Go** 并肩的极高性能(归功于 Starlette 和 Pydantic)。[最快的 Python web 框架之一](#_11)。 * **高效编码**:提高功能开发速度约 200% 至 300%。* * **更少 bug**:减少约 40% 的人为(开发者)导致错误。* From 3c20b6e42b13f266a4e9652b793c042cefea3228 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 14:34:13 +0000 Subject: [PATCH 10/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 02d2a088a..d5957c6fb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). * 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). * 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). From d0027de64f96911c4083f3f6a9fc69ee5ce4a77f Mon Sep 17 00:00:00 2001 From: Vladislav Kramorenko <85196001+Xewus@users.noreply.github.com> Date: Sat, 7 Jan 2023 17:45:32 +0300 Subject: [PATCH 11/34] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translatio?= =?UTF-8?q?n=20for=20`docs/ru/docs/fastapi-people.md`=20(#5577)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/ru/docs/fastapi-people.md | 180 +++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 docs/ru/docs/fastapi-people.md diff --git a/docs/ru/docs/fastapi-people.md b/docs/ru/docs/fastapi-people.md new file mode 100644 index 000000000..64ae66a03 --- /dev/null +++ b/docs/ru/docs/fastapi-people.md @@ -0,0 +1,180 @@ + +# Люди, поддерживающие FastAPI + +У FastAPI замечательное сообщество, которое доброжелательно к людям с любым уровнем знаний. + +## Создатель и хранитель + +Ку! 👋 + +Это я: + +{% if people %} +
+{% for user in people.maintainers %} + +
@{{ user.login }}
Answers: {{ user.answers }}
Pull Requests: {{ user.prs }}
+{% endfor %} + +
+{% endif %} + +Я создал и продолжаю поддерживать **FastAPI**. Узнать обо мне больше можно тут [Помочь FastAPI - Получить помощь - Связаться с автором](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}. + +... но на этой странице я хочу показать вам наше сообщество. + +--- + +**FastAPI** получает огромную поддержку от своего сообщества. И я хочу отметить вклад его участников. + +Это люди, которые: + +* [Помогают другим с их проблемами (вопросами) на GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}. +* [Создают пул-реквесты](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}. +* Делают ревью пул-реквестов, [что особенно важно для переводов на другие языки](contributing.md#translations){.internal-link target=_blank}. + +Поаплодируем им! 👏 🙇 + +## Самые активные участники за прошедший месяц + +Эти участники [оказали наибольшую помощь другим с решением их проблем (вопросов) на GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} в течение последнего месяца. ☕ + +{% if people %} +
+{% for user in people.last_month_active %} + +
@{{ user.login }}
Issues replied: {{ user.count }}
+{% endfor %} + +
+{% endif %} + +## Эксперты + +Здесь представлены **Эксперты FastAPI**. 🤓 + +Эти участники [оказали наибольшую помощь другим с решением их проблем (вопросов) на GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} за *всё время*. + +Оказывая помощь многим другим, они подтвердили свой уровень знаний. ✨ + +{% if people %} +
+{% for user in people.experts %} + +
@{{ user.login }}
Issues replied: {{ user.count }}
+{% endfor %} + +
+{% endif %} + +## Рейтинг участников, внёсших вклад в код + +Здесь представлен **Рейтинг участников, внёсших вклад в код**. 👷 + +Эти люди [сделали наибольшее количество пул-реквестов](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}, *включённых в основной код*. + +Они сделали наибольший вклад в исходный код, документацию, переводы и т.п. 📦 + +{% if people %} +
+{% for user in people.top_contributors %} + +
@{{ user.login }}
Pull Requests: {{ user.count }}
+{% endfor %} + +
+{% endif %} + +На самом деле таких людей довольно много (более сотни), вы можете увидеть всех на этой странице FastAPI GitHub Contributors page. 👷 + +## Рейтинг ревьюеров + +Здесь представлен **Рейтинг ревьюеров**. 🕵️ + +### Проверки переводов на другие языки + +Я знаю не очень много языков (и не очень хорошо 😅). +Итак, ревьюеры - это люди, которые могут [**подтвердить предложенный вами перевод** документации](contributing.md#translations){.internal-link target=_blank}. Без них не было бы документации на многих языках. + +--- + +В **Рейтинге ревьюеров** 🕵️ представлены те, кто проверил наибольшее количество пул-реквестов других участников, обеспечивая качество кода, документации и, особенно, **переводов на другие языки**. + +{% if people %} +
+{% for user in people.top_reviewers %} + +
@{{ user.login }}
Reviews: {{ user.count }}
+{% endfor %} + +
+{% endif %} + +## Спонсоры + +Здесь представлены **Спонсоры**. 😎 + +Спонсоры поддерживают мою работу над **FastAPI** (и другими проектами) главным образом через GitHub Sponsors. + +{% if sponsors %} + +{% if sponsors.gold %} + +### Золотые спонсоры + +{% for sponsor in sponsors.gold -%} + +{% endfor %} +{% endif %} + +{% if sponsors.silver %} + +### Серебрянные спонсоры + +{% for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + +{% if sponsors.bronze %} + +### Бронзовые спонсоры + +{% for sponsor in sponsors.bronze -%} + +{% endfor %} +{% endif %} + +{% endif %} + +### Индивидуальные спонсоры + +{% if github_sponsors %} +{% for group in github_sponsors.sponsors %} + +
+ +{% for user in group %} +{% if user.login not in sponsors_badge.logins %} + + + +{% endif %} +{% endfor %} + +
+ +{% endfor %} +{% endif %} + +## О данных - технические детали + +Основная цель этой страницы - подчеркнуть усилия сообщества по оказанию помощи другим. + +Особенно это касается усилий, которые обычно менее заметны и во многих случаях более трудоемки, таких как помощь другим в решении проблем и проверка пул-реквестов с переводами. + +Данные рейтинги подсчитываются каждый месяц, ознакомиться с тем, как это работает можно тут. + +Кроме того, я также подчеркиваю вклад спонсоров. + +И я оставляю за собой право обновлять алгоритмы подсчёта, виды рейтингов, пороговые значения и т.д. (так, на всякий случай 🤷). From 59d654672f0bdc75a5cab772c50172dc987991e6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 14:46:09 +0000 Subject: [PATCH 12/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d5957c6fb..fc544f23d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). * 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). * 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). * 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). From 2583a83f9dab0e35b7e82e01c8524253f547b562 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 7 Jan 2023 15:54:59 +0100 Subject: [PATCH 13/34] =?UTF-8?q?=F0=9F=91=B7=20Add=20GitHub=20Action=20ga?= =?UTF-8?q?te/check=20(#5492)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddc43c942..1235516d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,3 +75,19 @@ jobs: with: name: coverage-html path: htmlcov + + # https://github.com/marketplace/actions/alls-green#why + check: # This job does nothing and is only used for the branch protection + + if: always() + + needs: + - coverage-combine + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} From 9812116dc77318b1bfc98778ccaf775ee0433bf3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 14:55:35 +0000 Subject: [PATCH 14/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fc544f23d..3d0955145 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). * 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). * 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). * 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). From 6e1152d31fd4a849dcb50fbed9a0b4c14f50bebc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:08:12 +0000 Subject: [PATCH 15/34] =?UTF-8?q?=E2=AC=86=20Bump=20pypa/gh-action-pypi-pu?= =?UTF-8?q?blish=20from=201.5.2=20to=201.6.4=20(#5750)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8ffb493a4..c2fdb8e17 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -31,7 +31,7 @@ jobs: - name: Build distribution run: python -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.5.2 + uses: pypa/gh-action-pypi-publish@v1.6.4 with: password: ${{ secrets.PYPI_API_TOKEN }} - name: Dump GitHub context From adef9f4c02d007bcaacf93548328d8e4be3f490a Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 15:08:57 +0000 Subject: [PATCH 16/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3d0955145..4786f6601 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). * 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). * 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). From f4e895bc8a6dad274c9dcf006f491da064cd34f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:12:49 +0000 Subject: [PATCH 17/34] =?UTF-8?q?=E2=AC=86=20Bump=20types-ujson=20from=205?= =?UTF-8?q?.5.0=20to=205.6.0.0=20(#5735)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 55856cf36..f9045ef0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ test = [ "passlib[bcrypt] >=1.7.2,<2.0.0", # types - "types-ujson ==5.5.0", + "types-ujson ==5.6.0.0", "types-orjson ==3.6.2", ] doc = [ From 929c70011707b138cf9c2b8fcfbafc647ee8a90f Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 15:13:27 +0000 Subject: [PATCH 18/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4786f6601..bb8ec20af 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). * 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). From bea1fdd2eb34c9933bf66f08f9cc164ca97d99f1 Mon Sep 17 00:00:00 2001 From: Kelby Faessler Date: Sat, 7 Jan 2023 10:31:03 -0500 Subject: [PATCH 19/34] =?UTF-8?q?=E2=9C=8F=20Fix=20typo=20in=20`docs/en/do?= =?UTF-8?q?cs/deployment/concepts.md`=20(#5824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/deployment/concepts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md index 22604ceeb..77419f8b0 100644 --- a/docs/en/docs/deployment/concepts.md +++ b/docs/en/docs/deployment/concepts.md @@ -235,7 +235,7 @@ Here are some possible combinations and strategies: * One Uvicorn **process manager** would listen on the **IP** and **port**, and it would start **multiple Uvicorn worker processes** * **Kubernetes** and other distributed **container systems** * Something in the **Kubernetes** layer would listen on the **IP** and **port**. The replication would be by having **multiple containers**, each with **one Uvicorn process** running -* **Cloud services** that handle this for your +* **Cloud services** that handle this for you * The cloud service will probably **handle replication for you**. It would possibly let you define **a process to run**, or a **container image** to use, in any case, it would most probably be **a single Uvicorn process**, and the cloud service would be in charge of replicating it. !!! tip From 789d649fbadea706e90e219049e9326689e881db Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 15:31:38 +0000 Subject: [PATCH 20/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bb8ec20af..91bb9c2cb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). * ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). From 2dfdcea69addd9ac31db48190b53316b910a7865 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:35:14 +0000 Subject: [PATCH 21/34] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20(#5825)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions Co-authored-by: Sebastián Ramírez --- docs/en/data/github_sponsors.yml | 107 +++++++++++++--------------- docs/en/data/people.yml | 116 ++++++++++++++----------------- 2 files changed, 103 insertions(+), 120 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 1953df801..3d6831db6 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -2,15 +2,9 @@ sponsors: - - login: jina-ai avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4 url: https://github.com/jina-ai -- - login: Doist - avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 - url: https://github.com/Doist - - login: cryptapi +- - login: cryptapi avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 url: https://github.com/cryptapi - - login: jrobbins-LiveData - avatarUrl: https://avatars.githubusercontent.com/u/79278744?u=bae8175fc3f09db281aca1f97a9ddc1a914a8c4f&v=4 - url: https://github.com/jrobbins-LiveData - - login: nihpo avatarUrl: https://avatars.githubusercontent.com/u/1841030?u=0264956d7580f7e46687a762a7baa629f84cf97c&v=4 url: https://github.com/nihpo @@ -32,24 +26,21 @@ sponsors: - login: investsuite avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4 url: https://github.com/investsuite + - login: svix + avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 + url: https://github.com/svix - login: VincentParedes avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4 url: https://github.com/VincentParedes - - login: getsentry avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4 url: https://github.com/getsentry -- - login: InesIvanova - avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 - url: https://github.com/InesIvanova - - login: vyos avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4 url: https://github.com/vyos - login: SendCloud avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4 url: https://github.com/SendCloud - - login: matallan - avatarUrl: https://avatars.githubusercontent.com/u/12107723?v=4 - url: https://github.com/matallan - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya @@ -65,12 +56,12 @@ sponsors: - login: BoostryJP avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 url: https://github.com/BoostryJP +- - login: InesIvanova + avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 + url: https://github.com/InesIvanova - - login: johnadjei avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4 url: https://github.com/johnadjei - - login: gvisniuc - avatarUrl: https://avatars.githubusercontent.com/u/1614747?u=502dfdb2b087ddcf5460026297c98c7907bc2795&v=4 - url: https://github.com/gvisniuc - login: HiredScore avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 url: https://github.com/HiredScore @@ -80,6 +71,9 @@ sponsors: - login: Lovage-Labs avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4 url: https://github.com/Lovage-Labs +- - login: xshapira + avatarUrl: https://avatars.githubusercontent.com/u/48856190?u=3b0927ad29addab29a43767b52e45bee5cd6da9f&v=4 + url: https://github.com/xshapira - - login: moellenbeck avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4 url: https://github.com/moellenbeck @@ -95,6 +89,9 @@ sponsors: - login: dorianturba avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4 url: https://github.com/dorianturba + - login: Qazzquimby + avatarUrl: https://avatars.githubusercontent.com/u/12368310?u=f4ed4a7167fd359cfe4502d56d7c64f9bf59bb38&v=4 + url: https://github.com/Qazzquimby - login: jmaralc avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 url: https://github.com/jmaralc @@ -107,12 +104,15 @@ sponsors: - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io -- - login: indeedeng +- - login: guivaloz + avatarUrl: https://avatars.githubusercontent.com/u/1296621?u=bc4fc28f96c654aa2be7be051d03a315951e2491&v=4 + url: https://github.com/guivaloz + - login: indeedeng avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4 url: https://github.com/indeedeng - - login: A-Edge - avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 - url: https://github.com/A-Edge + - login: fratambot + avatarUrl: https://avatars.githubusercontent.com/u/20300069?u=41c85ea08960c8a8f0ce967b780e242b1454690c&v=4 + url: https://github.com/fratambot - - login: Kludex avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex @@ -152,9 +152,6 @@ sponsors: - login: jqueguiner avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4 url: https://github.com/jqueguiner - - login: alexsantos - avatarUrl: https://avatars.githubusercontent.com/u/932219?v=4 - url: https://github.com/alexsantos - login: tcsmith avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4 url: https://github.com/tcsmith @@ -164,6 +161,9 @@ sponsors: - login: mrkmcknz avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4 url: https://github.com/mrkmcknz + - login: theonlynexus + avatarUrl: https://avatars.githubusercontent.com/u/1515004?v=4 + url: https://github.com/theonlynexus - login: coffeewasmyidea avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4 url: https://github.com/coffeewasmyidea @@ -185,9 +185,6 @@ sponsors: - login: ColliotL avatarUrl: https://avatars.githubusercontent.com/u/3412402?u=ca64b07ecbef2f9da1cc2cac3f37522aa4814902&v=4 url: https://github.com/ColliotL - - login: grillazz - avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=453cd1725c8d7fe3e258016bc19cff861d4fcb53&v=4 - url: https://github.com/grillazz - login: dblackrun avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 url: https://github.com/dblackrun @@ -218,12 +215,6 @@ sponsors: - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen - - login: Rey8d01 - avatarUrl: https://avatars.githubusercontent.com/u/4836190?u=5942598a23a377602c1669522334ab5ebeaf9165&v=4 - url: https://github.com/Rey8d01 - - login: ScrimForever - avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4 - url: https://github.com/ScrimForever - login: ennui93 avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4 url: https://github.com/ennui93 @@ -257,9 +248,9 @@ sponsors: - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 url: https://github.com/wdwinslow - - login: bapi24 - avatarUrl: https://avatars.githubusercontent.com/u/11890901?u=45cc721d8f66ad2f62b086afc3d4761d0c16b9c6&v=4 - url: https://github.com/bapi24 + - login: jacobkrit + avatarUrl: https://avatars.githubusercontent.com/u/11823915?u=4921a7ea429b7eadcad3077f119f90d15a3318b2&v=4 + url: https://github.com/jacobkrit - login: svats2k avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4 url: https://github.com/svats2k @@ -278,11 +269,8 @@ sponsors: - login: wedwardbeck avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4 url: https://github.com/wedwardbeck - - login: m4knV - avatarUrl: https://avatars.githubusercontent.com/u/19666130?u=843383978814886be93c137d10d2e20e9f13af07&v=4 - url: https://github.com/m4knV - login: Filimoa - avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=0be845711495bbd7b756e13fcaeb8efc1ebd78ba&v=4 url: https://github.com/Filimoa - login: shuheng-liu avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4 @@ -317,9 +305,6 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure - - login: faviasono - avatarUrl: https://avatars.githubusercontent.com/u/37707874?u=f0b75ca4248987c08ed8fb8ed682e7e74d5d7091&v=4 - url: https://github.com/faviasono - login: ybressler avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4 url: https://github.com/ybressler @@ -341,6 +326,9 @@ sponsors: - login: dazeddd avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4 url: https://github.com/dazeddd + - login: A-Edge + avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 + url: https://github.com/A-Edge - login: yakkonaut avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4 url: https://github.com/yakkonaut @@ -359,9 +347,6 @@ sponsors: - login: anthonycepeda avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4 url: https://github.com/anthonycepeda - - login: fpiem - avatarUrl: https://avatars.githubusercontent.com/u/77389987?u=f667a25cd4832b28801189013b74450e06cc232c&v=4 - url: https://github.com/fpiem - login: DelfinaCare avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 url: https://github.com/DelfinaCare @@ -404,9 +389,6 @@ sponsors: - login: dmig avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4 url: https://github.com/dmig - - login: rinckd - avatarUrl: https://avatars.githubusercontent.com/u/546002?u=8ec88ab721a5636346f19dcd677a6f323058be8b&v=4 - url: https://github.com/rinckd - login: securancy avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4 url: https://github.com/securancy @@ -431,6 +413,9 @@ sponsors: - login: WillHogan avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 url: https://github.com/WillHogan + - login: my3 + avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 + url: https://github.com/my3 - login: cbonoz avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4 url: https://github.com/cbonoz @@ -443,6 +428,9 @@ sponsors: - login: igorcorrea avatarUrl: https://avatars.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4 url: https://github.com/igorcorrea + - login: larsvik + avatarUrl: https://avatars.githubusercontent.com/u/3442226?v=4 + url: https://github.com/larsvik - login: anthonycorletti avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4 url: https://github.com/anthonycorletti @@ -519,7 +507,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4 url: https://github.com/paulowiz - login: yannicschroeer - avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=4df05a7296c207b91c5d7c7a11c29df5ab313e2b&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=91515328b5418a4e7289a83f0dcec3573f1a6500&v=4 url: https://github.com/yannicschroeer - login: ghandic avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 @@ -528,7 +516,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4 url: https://github.com/fstau - login: pers0n4 - avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=444441027bc2c9f9db68e8047d65ff23d25699cf&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=7e5d2bf26d0a0670ea347f7db5febebc4e031ed1&v=4 url: https://github.com/pers0n4 - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 @@ -564,7 +552,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/38921751?u=ae14bc1e40f2dd5a9c5741fc0b0dffbd416a5fa9&v=4 url: https://github.com/ww-daniel-mora - login: rwxd - avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=9ddf8023ca3326381ba8fb77285ae36598a15de3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=b3cb7a606207141c357e517071cf91a67fb5577e&v=4 url: https://github.com/rwxd - login: ilias-ant avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4 @@ -602,16 +590,16 @@ sponsors: - login: realabja avatarUrl: https://avatars.githubusercontent.com/u/66185192?u=001e2dd9297784f4218997981b4e6fa8357bb70b&v=4 url: https://github.com/realabja - - login: alessio-proietti - avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4 - url: https://github.com/alessio-proietti - login: pondDevThai avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4 url: https://github.com/pondDevThai -- - login: wardal - avatarUrl: https://avatars.githubusercontent.com/u/15804042?v=4 - url: https://github.com/wardal - - login: gabrielmbmb + - login: zeb0x01 + avatarUrl: https://avatars.githubusercontent.com/u/77236545?u=c62bfcfbd463f9cf171c879cea1362a63de2c582&v=4 + url: https://github.com/zeb0x01 + - login: lironmiz + avatarUrl: https://avatars.githubusercontent.com/u/91504420?u=cb93dfec613911ac8d4e84fbb560711546711ad5&v=4 + url: https://github.com/lironmiz +- - login: gabrielmbmb avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4 url: https://github.com/gabrielmbmb - login: danburonline @@ -620,3 +608,6 @@ sponsors: - login: Moises6669 avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4 url: https://github.com/Moises6669 + - login: lyuboparvanov + avatarUrl: https://avatars.githubusercontent.com/u/106192895?u=367329c777320e01550afda9d8de670436181d86&v=4 + url: https://github.com/lyuboparvanov diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 51940a6b1..d46ec44ae 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,12 +1,12 @@ maintainers: - login: tiangolo - answers: 1837 - prs: 360 + answers: 1878 + prs: 361 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 374 + count: 379 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu @@ -34,7 +34,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: iudeen - count: 87 + count: 103 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 url: https://github.com/iudeen - login: raphaelauv @@ -45,14 +45,14 @@ experts: count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik +- login: jgould22 + count: 68 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: falkben count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 url: https://github.com/falkben -- login: jgould22 - count: 55 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 - login: sm-Fifteen count: 50 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 @@ -66,8 +66,8 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa - login: adriangb - count: 40 - avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=75087f0cf0e9f725f3cd18a899218b6c63ae60d3&v=4 + count: 41 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4 url: https://github.com/adriangb - login: includeamin count: 39 @@ -82,7 +82,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 url: https://github.com/chbndrhnns - login: frankie567 - count: 33 + count: 34 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 url: https://github.com/frankie567 - login: prostomarkeloff @@ -97,14 +97,14 @@ experts: count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 url: https://github.com/krishnardt +- login: panla + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 + url: https://github.com/panla - login: wshayes count: 29 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes -- login: panla - count: 29 - avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 - url: https://github.com/panla - login: ghandic count: 25 avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 @@ -169,6 +169,10 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny +- login: hellocoldworld + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4 + url: https://github.com/hellocoldworld - login: jonatasoli count: 15 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 @@ -177,14 +181,14 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 url: https://github.com/mbroton -- login: hellocoldworld - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4 - url: https://github.com/hellocoldworld - login: haizaar count: 13 avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4 url: https://github.com/haizaar +- login: n8sty + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: valentin994 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4 @@ -193,43 +197,31 @@ experts: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4 url: https://github.com/David-Lor -- login: n8sty - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty last_month_active: -- login: jgould22 - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: yinziyan1206 - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 - login: iudeen - count: 8 + count: 16 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 url: https://github.com/iudeen +- login: jgould22 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: NewSouthMjos + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/77476573?v=4 + url: https://github.com/NewSouthMjos +- login: davismartens + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/69799848?u=dbdfd256dd4e0a12d93efb3463225f3e39d8df6f&v=4 + url: https://github.com/davismartens - login: Kludex - count: 5 + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex -- login: JarroVGIT - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 - url: https://github.com/JarroVGIT -- login: TheJumpyWizard - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/90986815?u=67e9c13c9f063dd4313db7beb64eaa2f3a37f1fe&v=4 - url: https://github.com/TheJumpyWizard -- login: mbroton +- login: Lenclove count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 - url: https://github.com/mbroton -- login: mateoradman - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/48420316?u=066f36b8e8e263b0d90798113b0f291d3266db7c&v=4 - url: https://github.com/mateoradman + avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 + url: https://github.com/Lenclove top_contributors: - login: waynerv count: 25 @@ -269,7 +261,7 @@ top_contributors: url: https://github.com/Serrones - login: RunningIkkyu count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 url: https://github.com/RunningIkkyu - login: hard-coders count: 7 @@ -337,15 +329,15 @@ top_reviewers: avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: BilalAlpaslan - count: 70 + count: 72 avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 url: https://github.com/BilalAlpaslan - login: yezz123 - count: 59 + count: 66 avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 url: https://github.com/yezz123 - login: tokusumi - count: 50 + count: 51 avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 url: https://github.com/tokusumi - login: waynerv @@ -360,6 +352,10 @@ top_reviewers: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd +- login: iudeen + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: cikay count: 41 avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 @@ -372,10 +368,6 @@ top_reviewers: count: 33 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 url: https://github.com/AdrianDeAnda -- login: iudeen - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen - login: ArcLightSlavik count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 @@ -446,7 +438,7 @@ top_reviewers: url: https://github.com/sh0nk - login: RunningIkkyu count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 url: https://github.com/RunningIkkyu - login: LorhanSohaky count: 11 @@ -474,7 +466,7 @@ top_reviewers: url: https://github.com/ComicShrimp - login: peidrao count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=39edf7052371484cb488277638c23e1f6b584f4b&v=4 url: https://github.com/peidrao - login: izaguerreiro count: 9 @@ -496,6 +488,10 @@ top_reviewers: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 url: https://github.com/bezaca +- login: dimaqq + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 + url: https://github.com/dimaqq - login: raphaelauv count: 8 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 @@ -512,10 +508,6 @@ top_reviewers: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 url: https://github.com/NinaHwang -- login: dimaqq - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 - url: https://github.com/dimaqq - login: Xewus count: 8 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=4bdd4a0300530a504987db27488ba79c37f2fb18&v=4 From d202598c71c33301f65c58456fb8f3102cea597d Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 15:35:51 +0000 Subject: [PATCH 22/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 91bb9c2cb..ce8f63ee4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). * ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). * ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). From a17da3d0f4a0ac77e8c007455e60bbee7c6ab911 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 20:55:29 +0400 Subject: [PATCH 23/34] =?UTF-8?q?=E2=AC=86=20Bump=20dawidd6/action-downloa?= =?UTF-8?q?d-artifact=20from=202.24.2=20to=202.24.3=20(#5842)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- .github/workflows/preview-docs.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index 7d31a9c64..2af56e2bc 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -16,7 +16,7 @@ jobs: rm -rf ./site mkdir ./site - name: Download Artifact Docs - uses: dawidd6/action-download-artifact@v2.24.2 + uses: dawidd6/action-download-artifact@v2.24.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: build-docs.yml diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 7559c24c0..d6206d697 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -20,7 +20,7 @@ jobs: - run: pip install smokeshow - - uses: dawidd6/action-download-artifact@v2.24.2 + - uses: dawidd6/action-download-artifact@v2.24.3 with: workflow: test.yml commit: ${{ github.event.workflow_run.head_sha }} From 903e3be3b86bab3e4dff81243191ee139f8d33ee Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 16:56:07 +0000 Subject: [PATCH 24/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ce8f63ee4..4bef2e215 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). * ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). * ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). From 78813a543dfd5e2f0031c70a3cb12dcadc187cd6 Mon Sep 17 00:00:00 2001 From: Nonso Mgbechi Date: Sat, 7 Jan 2023 17:56:58 +0100 Subject: [PATCH 25/34] =?UTF-8?q?=E2=9C=8F=20Fix=20typo=20in=20`docs/en/do?= =?UTF-8?q?cs/async.md`=20(#5785)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/en/docs/async.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 6f34a9c9c..3d4b1956a 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -283,7 +283,7 @@ For example: ### Concurrency + Parallelism: Web + Machine Learning -With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attractive of NodeJS). +With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attraction of NodeJS). But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems. From 5c6d7b2ff3635a2880695c59804e26a5f4744c8b Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 16:57:45 +0000 Subject: [PATCH 26/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4bef2e215..040f61994 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). * ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). * ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). From f56b0d571dc2e49c9f1361947725e49d2d54a385 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 17:01:21 +0000 Subject: [PATCH 27/34] =?UTF-8?q?=E2=AC=86=20Update=20uvicorn[standard]=20?= =?UTF-8?q?requirement=20from=20<0.19.0,>=3D0.12.0=20to=20>=3D0.12.0,<0.21?= =?UTF-8?q?.0=20for=20development=20(#5795)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f9045ef0a..1983f2e51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,7 +88,7 @@ doc = [ ] dev = [ "ruff ==0.0.138", - "uvicorn[standard] >=0.12.0,<0.19.0", + "uvicorn[standard] >=0.12.0,<0.21.0", "pre-commit >=2.17.0,<3.0.0", ] all = [ From 27ce2e2108001c1709cc0c321a4e29fcc5d5bd7a Mon Sep 17 00:00:00 2001 From: Xhy-5000 <45428960+Xhy-5000@users.noreply.github.com> Date: Sat, 7 Jan 2023 12:01:38 -0500 Subject: [PATCH 28/34] =?UTF-8?q?=F0=9F=93=9D=20Add=20External=20Link:=20A?= =?UTF-8?q?uthorization=20on=20FastAPI=20with=20Casbin=20(#5712)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/en/data/external_links.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/data/external_links.yml b/docs/en/data/external_links.yml index 934c5842b..b7db15038 100644 --- a/docs/en/data/external_links.yml +++ b/docs/en/data/external_links.yml @@ -1,5 +1,9 @@ articles: english: + - author: Teresa N. Fontanella De Santis + author_link: https://dev.to/ + link: https://dev.to/teresafds/authorization-on-fastapi-with-casbin-41og + title: Authorization on FastAPI with Casbin - author: WayScript author_link: https://www.wayscript.com link: https://blog.wayscript.com/fast-api-quickstart/ From eb39b0f8f8093c1046ca2a58b38dd308976d8bcd Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 17:01:58 +0000 Subject: [PATCH 29/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 040f61994..5c6f90401 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). * ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). * ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). From 681e5c0199863c2588fd962d49c9e6b637dc4e51 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 17:02:15 +0000 Subject: [PATCH 30/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5c6f90401..95fae8fe0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 📝 Add External Link: Authorization on FastAPI with Casbin. PR [#5712](https://github.com/tiangolo/fastapi/pull/5712) by [@Xhy-5000](https://github.com/Xhy-5000). * ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). * ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). * ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). From c482dd3d425e774af743b801e2705da8828f2b5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 17:04:43 +0000 Subject: [PATCH 31/34] =?UTF-8?q?=E2=AC=86=20Update=20coverage[toml]=20req?= =?UTF-8?q?uirement=20from=20<7.0,>=3D6.5.0=20to=20>=3D6.5.0,<8.0=20(#5801?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1983f2e51..b29549f5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ Documentation = "https://fastapi.tiangolo.com/" [project.optional-dependencies] test = [ "pytest >=7.1.3,<8.0.0", - "coverage[toml] >= 6.5.0,<7.0", + "coverage[toml] >= 6.5.0,< 8.0", "mypy ==0.982", "ruff ==0.0.138", "black == 22.10.0", From aa6a8e5d4908994318069710e8d0ce62daf67ce2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 7 Jan 2023 17:05:20 +0000 Subject: [PATCH 32/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 95fae8fe0..0ed6c1b1d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0. PR [#5801](https://github.com/tiangolo/fastapi/pull/5801) by [@dependabot[bot]](https://github.com/apps/dependabot). * 📝 Add External Link: Authorization on FastAPI with Casbin. PR [#5712](https://github.com/tiangolo/fastapi/pull/5712) by [@Xhy-5000](https://github.com/Xhy-5000). * ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). * ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). From a6af7c27f8edb138ea7887125a8471764c58c531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Jan 2023 21:15:11 +0400 Subject: [PATCH 33/34] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 58 ++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0ed6c1b1d..dcbc0254a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,22 +2,66 @@ ## Latest Changes -* ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0. PR [#5801](https://github.com/tiangolo/fastapi/pull/5801) by [@dependabot[bot]](https://github.com/apps/dependabot). +### Features + +* ✨ Add support for function return type annotations to declare the `response_model`. Initial PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). + +Now you can declare the return type / `response_model` in the function return type annotation: + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + + +@app.get("/items/") +async def read_items() -> list[Item]: + return [ + Item(name="Portal Gun", price=42.0), + Item(name="Plumbus", price=32.0), + ] +``` + +FastAPI will use the return type annotation to perform: + +* Data validation +* Automatic documentation + * It could power automatic client generators +* **Data filtering** + +Before this version it was only supported via the `response_model` parameter. + +Read more about it in the new docs: [Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/). + +### Docs + * 📝 Add External Link: Authorization on FastAPI with Casbin. PR [#5712](https://github.com/tiangolo/fastapi/pull/5712) by [@Xhy-5000](https://github.com/Xhy-5000). -* ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). * ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). +* ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). +* 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). +* 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). + +### Internal + +* ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0. PR [#5801](https://github.com/tiangolo/fastapi/pull/5801) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). -* ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). * ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). -* 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). -* 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). -* 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). * 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). -* ✨ Add support for function return type annotations to declare the `response_model`. PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). * ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo). From 69bd7d8501fe77601ebd67f55b39596fdd1e3792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Jan 2023 21:17:10 +0400 Subject: [PATCH 34/34] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.89.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dcbc0254a..cdafa6899 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,8 @@ ## Latest Changes +## 0.89.0 + ### Features * ✨ Add support for function return type annotations to declare the `response_model`. Initial PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 037d9804b..bda10f043 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.88.0" +__version__ = "0.89.0" from starlette import status as status