From e10a4375f983b7b87ec6873b3c0b48cb482efbab Mon Sep 17 00:00:00 2001 From: Austin Orr Date: Wed, 5 May 2021 11:20:56 -0700 Subject: [PATCH] =?utf8?q?=E2=9C=A8=20Add=20support=20for=20adding=20multi?= =?utf8?q?ple=20examples=20in=20request=20bodies=20and=20path,=20query,=20?= =?utf8?q?cookie,=20and=20header=20params=20(#1267)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- .../docs/img/tutorial/body-fields/image02.png | Bin 0 -> 93828 bytes docs/en/docs/tutorial/schema-extra-example.md | 89 +- docs_src/schema_extra_example/tutorial004.py | 52 + fastapi/openapi/utils.py | 13 +- fastapi/param_functions.py | 31 +- fastapi/params.py | 36 +- tests/test_schema_extra_examples.py | 889 ++++++++++++++++++ .../test_schema_extra_example/__init__.py | 0 .../test_tutorial004.py | 134 +++ 9 files changed, 1220 insertions(+), 24 deletions(-) create mode 100644 docs/en/docs/img/tutorial/body-fields/image02.png create mode 100644 docs_src/schema_extra_example/tutorial004.py create mode 100644 tests/test_schema_extra_examples.py create mode 100644 tests/test_tutorial/test_schema_extra_example/__init__.py create mode 100644 tests/test_tutorial/test_schema_extra_example/test_tutorial004.py diff --git a/docs/en/docs/img/tutorial/body-fields/image02.png b/docs/en/docs/img/tutorial/body-fields/image02.png new file mode 100644 index 0000000000000000000000000000000000000000..f307bb8ecd30de3049e33025182616f1b9964be4 GIT binary patch literal 93828 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 literal 0 Hc-jL100001 diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index 11c89c084d..47ee8503a9 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -1,58 +1,109 @@ -# Schema Extra - Example +# Declare Request Example Data -You can define extra information to go in JSON Schema. +You can declare examples of the data your app can receive. -A common use case is to add an `example` that will be shown in the docs. - -There are several ways you can declare extra JSON Schema information. +Here are several ways to do it. ## Pydantic `schema_extra` -You can declare an example for a Pydantic model using `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization: +You can declare an `example` for a Pydantic model using `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization: ```Python hl_lines="15-23" {!../../../docs_src/schema_extra_example/tutorial001.py!} ``` -That extra info will be added as-is to the output JSON Schema. +That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs. + +!!! tip + You could use the same technique to extend the JSON Schema and add your own custom extra info. + + For example you could use it to add metadata for a frontend user interface, etc. ## `Field` additional arguments -In `Field`, `Path`, `Query`, `Body` and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an `example`: +When using `Field()` with Pydantic models, you can also declare extra info for the **JSON Schema** by passing any other arbitrary arguments to the function. + +You can use this to add `example` for each field: ```Python hl_lines="4 10-13" {!../../../docs_src/schema_extra_example/tutorial002.py!} ``` !!! warning - Keep in mind that those extra arguments passed won't add any validation, only annotation, for documentation purposes. + Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes. + +## `example` and `examples` in OpenAPI + +When using any of: -## `Body` additional arguments +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` -The same way you can pass extra info to `Field`, you can do the same with `Path`, `Query`, `Body`, etc. +you can also declare a data `example` or a group of `examples` with additional information that will be added to **OpenAPI**. -For example, you can pass an `example` for a body request to `Body`: +### `Body` with `example` + +Here we pass an `example` of the data expected in `Body()`: ```Python hl_lines="21-26" {!../../../docs_src/schema_extra_example/tutorial003.py!} ``` -## Example in the docs UI +### Example in the docs UI With any of the methods above it would look like this in the `/docs`: +### `Body` with multiple `examples` + +Alternatively to the single `example`, you can pass `examples` using a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too. + +The keys of the `dict` identify each example, and each value is another `dict`. + +Each specific example `dict` in the `examples` can contain: + +* `summary`: Short description for the example. +* `description`: A long description that can contain Markdown text. +* `value`: This is the actual example shown, e.g. a `dict`. +* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`. + +```Python hl_lines="22-48" +{!../../../docs_src/schema_extra_example/tutorial004.py!} +``` + +### Examples in the docs UI + +With `examples` added to `Body()` the `/docs` would look like: + + + ## Technical Details -About `example` vs `examples`... +!!! warning + These are very technical details about the standards **JSON Schema** and **OpenAPI**. + + If the ideas above already work for you, that might me enough, and you probably don't need these details, feel free to skip them. + +When you add an example inside of a Pydantic model, using `schema_extra` or `Field(example="something")` that example is added to the **JSON Schema** for that Pydantic model. + +And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI. + +**JSON Schema** doesn't really have a field `example` in the standards. Recent versions of JSON Schema define a field `examples`, but OpenAPI 3.0.3 is based on an older version of JSON Schema that didn't have `examples`. + +So, OpenAPI 3.0.3 defined its own `example` for the modified version of **JSON Schema** it uses, for the same purpose (but it's a single `example`, not `examples`), and that's what is used by the API docs UI (using Swagger UI). -JSON Schema defines a field `examples` in the most recent versions, but OpenAPI is based on an older version of JSON Schema that didn't have `examples`. +So, although `example` is not part of JSON Schema, it is part of OpenAPI's custom version of JSON Schema, and that's what will be used by the docs UI. -So, OpenAPI defined its own `example` for the same purpose (as `example`, not `examples`), and that's what is used by the docs UI (using Swagger UI). +But when you use `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples are not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they are added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema). -So, although `example` is not part of JSON Schema, it is part of OpenAPI, and that's what will be used by the docs UI. +For `Path()`, `Query()`, `Header()`, and `Cookie()`, the `example` or `examples` are added to the OpenAPI definition, to the `Parameter Object` (in the specification). -## Other info +And for `Body()`, `File()`, and `Form()`, the `example` or `examples` are equivalently added to the OpenAPI definition, to the `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification). -The same way, you could add your own custom extra info that would be added to the JSON Schema for each model, for example to customize a frontend user interface, etc. +On the other hand, there's a newer version of OpenAPI: **3.1.0**, recently released. It is based on the latest JSON Schema and most of the modifications from OpenAPI's custom version of JSON Schema are removed, in exchange of the features from the recent versions of JSON Schema, so all these small differences are reduced. Nevertheless, Swagger UI currently doesn't support OpenAPI 3.1.0, so, for now, it's better to continue using the ideas above. diff --git a/docs_src/schema_extra_example/tutorial004.py b/docs_src/schema_extra_example/tutorial004.py new file mode 100644 index 0000000000..9f0e8b4378 --- /dev/null +++ b/docs_src/schema_extra_example/tutorial004.py @@ -0,0 +1,52 @@ +from typing import Optional + +from fastapi import Body, FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: Optional[str] = None + price: float + tax: Optional[float] = None + + +@app.put("/items/{item_id}") +async def update_item( + *, + item_id: int, + item: Item = Body( + ..., + examples={ + "normal": { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, + }, + "converted": { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": { + "name": "Bar", + "price": "35.4", + }, + }, + "invalid": { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + }, + ), +): + results = {"item_id": item_id, "item": item} + return results diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 410ba9389c..6f749ef9c2 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -21,7 +21,7 @@ from fastapi.utils import ( get_model_definitions, ) from pydantic import BaseModel -from pydantic.fields import ModelField +from pydantic.fields import ModelField, Undefined from pydantic.schema import ( field_schema, get_flat_models_from_fields, @@ -101,6 +101,10 @@ def get_openapi_operation_parameters( } if field_info.description: parameter["description"] = field_info.description + if field_info.examples: + parameter["examples"] = jsonable_encoder(field_info.examples) + elif field_info.example != Undefined: + parameter["example"] = jsonable_encoder(field_info.example) if field_info.deprecated: parameter["deprecated"] = field_info.deprecated parameters.append(parameter) @@ -124,7 +128,12 @@ def get_openapi_operation_request_body( request_body_oai: Dict[str, Any] = {} if required: request_body_oai["required"] = required - request_body_oai["content"] = {request_media_type: {"schema": body_schema}} + request_media_content: Dict[str, Any] = {"schema": body_schema} + if field_info.examples: + request_media_content["examples"] = jsonable_encoder(field_info.examples) + elif field_info.example != Undefined: + request_media_content["example"] = jsonable_encoder(field_info.example) + request_body_oai["content"] = {request_media_type: request_media_content} return request_body_oai diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 9ebb591000..ff65d72712 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -1,6 +1,7 @@ -from typing import Any, Callable, Optional, Sequence +from typing import Any, Callable, Dict, Optional, Sequence from fastapi import params +from pydantic.fields import Undefined def Path( # noqa: N802 @@ -16,6 +17,8 @@ def Path( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ) -> Any: @@ -31,6 +34,8 @@ def Path( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, deprecated=deprecated, **extra, ) @@ -49,6 +54,8 @@ def Query( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ) -> Any: @@ -64,6 +71,8 @@ def Query( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, deprecated=deprecated, **extra, ) @@ -83,6 +92,8 @@ def Header( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ) -> Any: @@ -99,6 +110,8 @@ def Header( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, deprecated=deprecated, **extra, ) @@ -117,6 +130,8 @@ def Cookie( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ) -> Any: @@ -132,6 +147,8 @@ def Cookie( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, deprecated=deprecated, **extra, ) @@ -152,6 +169,8 @@ def Body( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ) -> Any: return params.Body( @@ -168,6 +187,8 @@ def Body( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, **extra, ) @@ -186,6 +207,8 @@ def Form( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ) -> Any: return params.Form( @@ -201,6 +224,8 @@ def Form( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, **extra, ) @@ -219,6 +244,8 @@ def File( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ) -> Any: return params.File( @@ -234,6 +261,8 @@ def File( # noqa: N802 min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, **extra, ) diff --git a/fastapi/params.py b/fastapi/params.py index aa3269a805..3cab98b78d 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -1,7 +1,7 @@ from enum import Enum -from typing import Any, Callable, Optional, Sequence +from typing import Any, Callable, Dict, Optional, Sequence -from pydantic.fields import FieldInfo +from pydantic.fields import FieldInfo, Undefined class ParamTypes(Enum): @@ -28,10 +28,14 @@ class Param(FieldInfo): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ): self.deprecated = deprecated + self.example = example + self.examples = examples super().__init__( default, alias=alias, @@ -68,6 +72,8 @@ class Path(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ): @@ -85,6 +91,8 @@ class Path(Param): max_length=max_length, regex=regex, deprecated=deprecated, + example=example, + examples=examples, **extra, ) @@ -106,6 +114,8 @@ class Query(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ): @@ -122,6 +132,8 @@ class Query(Param): max_length=max_length, regex=regex, deprecated=deprecated, + example=example, + examples=examples, **extra, ) @@ -144,6 +156,8 @@ class Header(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ): @@ -161,6 +175,8 @@ class Header(Param): max_length=max_length, regex=regex, deprecated=deprecated, + example=example, + examples=examples, **extra, ) @@ -182,6 +198,8 @@ class Cookie(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, deprecated: Optional[bool] = None, **extra: Any, ): @@ -198,6 +216,8 @@ class Cookie(Param): max_length=max_length, regex=regex, deprecated=deprecated, + example=example, + examples=examples, **extra, ) @@ -219,10 +239,14 @@ class Body(FieldInfo): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ): self.embed = embed self.media_type = media_type + self.example = example + self.examples = examples super().__init__( default, alias=alias, @@ -258,6 +282,8 @@ class Form(Body): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ): super().__init__( @@ -274,6 +300,8 @@ class Form(Body): min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, **extra, ) @@ -294,6 +322,8 @@ class File(Form): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, **extra: Any, ): super().__init__( @@ -309,6 +339,8 @@ class File(Form): min_length=min_length, max_length=max_length, regex=regex, + example=example, + examples=examples, **extra, ) diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py new file mode 100644 index 0000000000..3e0d846cd3 --- /dev/null +++ b/tests/test_schema_extra_examples.py @@ -0,0 +1,889 @@ +from fastapi import Body, Cookie, FastAPI, Header, Path, Query +from fastapi.testclient import TestClient +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + data: str + + class Config: + schema_extra = {"example": {"data": "Data in schema_extra"}} + + +@app.post("/schema_extra/") +def schema_extra(item: Item): + return item + + +@app.post("/example/") +def example(item: Item = Body(..., example={"data": "Data in Body example"})): + return item + + +@app.post("/examples/") +def examples( + item: Item = Body( + ..., + examples={ + "example1": { + "summary": "example1 summary", + "value": {"data": "Data in Body examples, example1"}, + }, + "example2": {"value": {"data": "Data in Body examples, example2"}}, + }, + ) +): + return item + + +@app.post("/example_examples/") +def example_examples( + item: Item = Body( + ..., + example={"data": "Overriden example"}, + examples={ + "example1": {"value": {"data": "examples example_examples 1"}}, + "example2": {"value": {"data": "examples example_examples 2"}}, + }, + ) +): + return item + + +# TODO: enable these tests once/if Form(embed=False) is supported +# TODO: In that case, define if File() should support example/examples too +# @app.post("/form_example") +# def form_example(firstname: str = Form(..., example="John")): +# return firstname + + +# @app.post("/form_examples") +# def form_examples( +# lastname: str = Form( +# ..., +# examples={ +# "example1": {"summary": "last name summary", "value": "Doe"}, +# "example2": {"value": "Doesn't"}, +# }, +# ), +# ): +# return lastname + + +# @app.post("/form_example_examples") +# def form_example_examples( +# lastname: str = Form( +# ..., +# example="Doe overriden", +# examples={ +# "example1": {"summary": "last name summary", "value": "Doe"}, +# "example2": {"value": "Doesn't"}, +# }, +# ), +# ): +# return lastname + + +@app.get("/path_example/{item_id}") +def path_example( + item_id: str = Path( + ..., + example="item_1", + ), +): + return item_id + + +@app.get("/path_examples/{item_id}") +def path_examples( + item_id: str = Path( + ..., + examples={ + "example1": {"summary": "item ID summary", "value": "item_1"}, + "example2": {"value": "item_2"}, + }, + ), +): + return item_id + + +@app.get("/path_example_examples/{item_id}") +def path_example_examples( + item_id: str = Path( + ..., + example="item_overriden", + examples={ + "example1": {"summary": "item ID summary", "value": "item_1"}, + "example2": {"value": "item_2"}, + }, + ), +): + return item_id + + +@app.get("/query_example/") +def query_example( + data: str = Query( + None, + example="query1", + ), +): + return data + + +@app.get("/query_examples/") +def query_examples( + data: str = Query( + None, + examples={ + "example1": {"summary": "Query example 1", "value": "query1"}, + "example2": {"value": "query2"}, + }, + ), +): + return data + + +@app.get("/query_example_examples/") +def query_example_examples( + data: str = Query( + None, + example="query_overriden", + examples={ + "example1": {"summary": "Qeury example 1", "value": "query1"}, + "example2": {"value": "query2"}, + }, + ), +): + return data + + +@app.get("/header_example/") +def header_example( + data: str = Header( + None, + example="header1", + ), +): + return data + + +@app.get("/header_examples/") +def header_examples( + data: str = Header( + None, + examples={ + "example1": {"summary": "header example 1", "value": "header1"}, + "example2": {"value": "header2"}, + }, + ), +): + return data + + +@app.get("/header_example_examples/") +def header_example_examples( + data: str = Header( + None, + example="header_overriden", + examples={ + "example1": {"summary": "Qeury example 1", "value": "header1"}, + "example2": {"value": "header2"}, + }, + ), +): + return data + + +@app.get("/cookie_example/") +def cookie_example( + data: str = Cookie( + None, + example="cookie1", + ), +): + return data + + +@app.get("/cookie_examples/") +def cookie_examples( + data: str = Cookie( + None, + examples={ + "example1": {"summary": "cookie example 1", "value": "cookie1"}, + "example2": {"value": "cookie2"}, + }, + ), +): + return data + + +@app.get("/cookie_example_examples/") +def cookie_example_examples( + data: str = Cookie( + None, + example="cookie_overriden", + examples={ + "example1": {"summary": "Qeury example 1", "value": "cookie1"}, + "example2": {"value": "cookie2"}, + }, + ), +): + return data + + +client = TestClient(app) + + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/schema_extra/": { + "post": { + "summary": "Schema Extra", + "operationId": "schema_extra_schema_extra__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/example/": { + "post": { + "summary": "Example", + "operationId": "example_example__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "example": {"data": "Data in Body example"}, + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/examples/": { + "post": { + "summary": "Examples", + "operationId": "examples_examples__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "example1": { + "summary": "example1 summary", + "value": { + "data": "Data in Body examples, example1" + }, + }, + "example2": { + "value": {"data": "Data in Body examples, example2"} + }, + }, + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/example_examples/": { + "post": { + "summary": "Example Examples", + "operationId": "example_examples_example_examples__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "example1": { + "value": {"data": "examples example_examples 1"} + }, + "example2": { + "value": {"data": "examples example_examples 2"} + }, + }, + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/path_example/{item_id}": { + "get": { + "summary": "Path Example", + "operationId": "path_example_path_example__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "example": "item_1", + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/path_examples/{item_id}": { + "get": { + "summary": "Path Examples", + "operationId": "path_examples_path_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "examples": { + "example1": { + "summary": "item ID summary", + "value": "item_1", + }, + "example2": {"value": "item_2"}, + }, + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/path_example_examples/{item_id}": { + "get": { + "summary": "Path Example Examples", + "operationId": "path_example_examples_path_example_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "examples": { + "example1": { + "summary": "item ID summary", + "value": "item_1", + }, + "example2": {"value": "item_2"}, + }, + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/query_example/": { + "get": { + "summary": "Query Example", + "operationId": "query_example_query_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "query1", + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/query_examples/": { + "get": { + "summary": "Query Examples", + "operationId": "query_examples_query_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Query example 1", + "value": "query1", + }, + "example2": {"value": "query2"}, + }, + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/query_example_examples/": { + "get": { + "summary": "Query Example Examples", + "operationId": "query_example_examples_query_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Qeury example 1", + "value": "query1", + }, + "example2": {"value": "query2"}, + }, + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/header_example/": { + "get": { + "summary": "Header Example", + "operationId": "header_example_header_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "header1", + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/header_examples/": { + "get": { + "summary": "Header Examples", + "operationId": "header_examples_header_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "header example 1", + "value": "header1", + }, + "example2": {"value": "header2"}, + }, + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/header_example_examples/": { + "get": { + "summary": "Header Example Examples", + "operationId": "header_example_examples_header_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Qeury example 1", + "value": "header1", + }, + "example2": {"value": "header2"}, + }, + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/cookie_example/": { + "get": { + "summary": "Cookie Example", + "operationId": "cookie_example_cookie_example__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "example": "cookie1", + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/cookie_examples/": { + "get": { + "summary": "Cookie Examples", + "operationId": "cookie_examples_cookie_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "cookie example 1", + "value": "cookie1", + }, + "example2": {"value": "cookie2"}, + }, + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/cookie_example_examples/": { + "get": { + "summary": "Cookie Example Examples", + "operationId": "cookie_example_examples_cookie_example_examples__get", + "parameters": [ + { + "required": False, + "schema": {"title": "Data", "type": "string"}, + "examples": { + "example1": { + "summary": "Qeury example 1", + "value": "cookie1", + }, + "example2": {"value": "cookie2"}, + }, + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["data"], + "type": "object", + "properties": {"data": {"title": "Data", "type": "string"}}, + "example": {"data": "Data in schema_extra"}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, +} + + +def test_openapi_schema(): + """ + Test that example overrides work: + + * pydantic model schema_extra is included + * Body(example={}) overrides schema_extra in pydantic model + * Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model + """ + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == openapi_schema + + +def test_call_api(): + response = client.post("/schema_extra/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/example/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/examples/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.post("/example_examples/", json={"data": "Foo"}) + assert response.status_code == 200, response.text + response = client.get("/path_example/foo") + assert response.status_code == 200, response.text + response = client.get("/path_examples/foo") + assert response.status_code == 200, response.text + response = client.get("/path_example_examples/foo") + assert response.status_code == 200, response.text + response = client.get("/query_example/") + assert response.status_code == 200, response.text + response = client.get("/query_examples/") + assert response.status_code == 200, response.text + response = client.get("/query_example_examples/") + assert response.status_code == 200, response.text + response = client.get("/header_example/") + assert response.status_code == 200, response.text + response = client.get("/header_examples/") + assert response.status_code == 200, response.text + response = client.get("/header_example_examples/") + assert response.status_code == 200, response.text + response = client.get("/cookie_example/") + assert response.status_code == 200, response.text + response = client.get("/cookie_examples/") + assert response.status_code == 200, response.text + response = client.get("/cookie_example_examples/") + assert response.status_code == 200, response.text diff --git a/tests/test_tutorial/test_schema_extra_example/__init__.py b/tests/test_tutorial/test_schema_extra_example/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py new file mode 100644 index 0000000000..89f5b66fd6 --- /dev/null +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -0,0 +1,134 @@ +from fastapi.testclient import TestClient + +from docs_src.schema_extra_example.tutorial004 import app + +client = TestClient(app) + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "normal": { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, + }, + "converted": { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, + }, + "invalid": { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + }, + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "tax": {"title": "Tax", "type": "number"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, +} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == openapi_schema + + +# Test required and embedded body parameters with no bodies sent +def test_post_body_example(): + response = client.put( + "/items/5", + json={ + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, + ) + assert response.status_code == 200 -- 2.47.3