mirror of https://github.com/tiangolo/fastapi.git
✨ Allow docstrings to be truncated before being used for OpenAPI (#556)
This commit is contained in:
parent
f5ccb3c35d
commit
c7dc26b760
|
|
@ -0,0 +1,30 @@
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class Item(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: str = None
|
||||||
|
price: float
|
||||||
|
tax: float = None
|
||||||
|
tags: Set[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/items/", response_model=Item, summary="Create an item")
|
||||||
|
async def create_item(*, item: Item):
|
||||||
|
"""
|
||||||
|
Create an item with all the information:
|
||||||
|
|
||||||
|
- **name**: each item must have a name
|
||||||
|
- **description**: a long description
|
||||||
|
- **price**: required
|
||||||
|
- **tax**: if the item doesn't have tax, you can omit this
|
||||||
|
- **tags**: a set of unique tag strings for this item
|
||||||
|
\f
|
||||||
|
:param item: User input.
|
||||||
|
"""
|
||||||
|
return item
|
||||||
|
|
@ -18,3 +18,15 @@ To exclude a path operation from the generated OpenAPI schema (and thus, from th
|
||||||
```Python hl_lines="6"
|
```Python hl_lines="6"
|
||||||
{!./src/path_operation_advanced_configuration/tutorial002.py!}
|
{!./src/path_operation_advanced_configuration/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Advanced description from docstring
|
||||||
|
|
||||||
|
You can limit the lines used from the docstring of a *path operation function* for OpenAPI.
|
||||||
|
|
||||||
|
Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate the output used for OpenAPI at this point.
|
||||||
|
|
||||||
|
It won't show up in the documentation, but other tools (such as Sphinx) will be able to use the rest.
|
||||||
|
|
||||||
|
```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
|
||||||
|
{!./src/path_operation_advanced_configuration/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,9 @@ class APIRoute(routing.Route):
|
||||||
self.dependencies = []
|
self.dependencies = []
|
||||||
self.summary = summary
|
self.summary = summary
|
||||||
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
|
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
|
||||||
|
# if a "form feed" character (page break) is found in the description text,
|
||||||
|
# truncate description text to the content preceding the first "form feed"
|
||||||
|
self.description = self.description.split("\f")[0]
|
||||||
self.response_description = response_description
|
self.response_description = response_description
|
||||||
self.responses = responses or {}
|
self.responses = responses or {}
|
||||||
response_fields = {}
|
response_fields = {}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
from starlette.testclient import TestClient
|
||||||
|
|
||||||
|
from path_operation_advanced_configuration.tutorial003 import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
openapi_schema = {
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
"info": {"title": "Fast API", "version": "0.1.0"},
|
||||||
|
"paths": {
|
||||||
|
"/items/": {
|
||||||
|
"post": {
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {"$ref": "#/components/schemas/Item"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"summary": "Create an item",
|
||||||
|
"description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item\n",
|
||||||
|
"operationId": "create_item_items__post",
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {"$ref": "#/components/schemas/Item"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Item": {
|
||||||
|
"title": "Item",
|
||||||
|
"required": ["name", "price"],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {"title": "Name", "type": "string"},
|
||||||
|
"price": {"title": "Price", "type": "number"},
|
||||||
|
"description": {"title": "Description", "type": "string"},
|
||||||
|
"tax": {"title": "Tax", "type": "number"},
|
||||||
|
"tags": {
|
||||||
|
"title": "Tags",
|
||||||
|
"uniqueItems": True,
|
||||||
|
"type": "array",
|
||||||
|
"items": {"type": "string"},
|
||||||
|
"default": [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"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"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"HTTPValidationError": {
|
||||||
|
"title": "HTTPValidationError",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"detail": {
|
||||||
|
"title": "Detail",
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_openapi_schema():
|
||||||
|
response = client.get("/openapi.json")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == openapi_schema
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_params_str_validations():
|
||||||
|
response = client.post("/items/", json={"name": "Foo", "price": 42})
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"name": "Foo",
|
||||||
|
"price": 42,
|
||||||
|
"description": None,
|
||||||
|
"tax": None,
|
||||||
|
"tags": [],
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue