Skip to content

Commit

Permalink
Merge pull request #76 from luolingchun/openapi_extra
Browse files Browse the repository at this point in the history
Openapi extra
  • Loading branch information
luolingchun authored Jun 4, 2023
2 parents 035c127 + e3b928a commit 1c51e53
Show file tree
Hide file tree
Showing 26 changed files with 860 additions and 373 deletions.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Checklist:

- [ ] Run `pytest tests` and no failed.
- [ ] Run `flake8 flask_openapi3 tests examples` and no failed.
- [ ] Run `mkdocs serve` and no failed.
- [ ] Run `mypy flask_openapi3` and no failed.
- [ ] Run `mkdocs serve` and no failed.
6 changes: 2 additions & 4 deletions docs/Example.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ class BookResponse(BaseModel):
tags=[book_tag],
summary='new summary',
description='new description',
responses={"200": BookResponse},
extra_responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}},
responses={"200": BookResponse, "201": {"content": {"text/csv": {"schema": {"type": "string"}}}}},
security=security
)
def get_book(path: BookPath):
Expand Down Expand Up @@ -189,7 +188,6 @@ from typing import Optional
from pydantic import BaseModel, Field

from flask_openapi3 import APIBlueprint, OpenAPI
from flask_openapi3 import HTTPBearer
from flask_openapi3 import Tag, Info

info = Info(title='book API', version='1.0.0')
Expand Down Expand Up @@ -238,7 +236,7 @@ def get_book():
return {"code": 0, "message": "ok"}


@api.post('/book', extra_responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
@api.post('/book', responses={"201": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
def create_book(body: BookBody):
assert body.age == 3
return {"code": 0, "message": "ok"}
Expand Down
105 changes: 105 additions & 0 deletions docs/Tutorial/Openapi_extra.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
*New in v2.4.0*

The [BaseModel](https://docs.pydantic.dev/latest/usage/models/) in [Pydantic](https://github.com/pydantic/pydantic)
supports some custom configurations([Model Config](https://docs.pydantic.dev/latest/usage/model_config/)),
so we can use the `openapi_extra` to extend OpenAPI Specification.

The `openapi_extra` will be merged with the automatically generated OpenAPI schema.

## form

```python
class UploadFilesForm(BaseModel):
file: FileStorage
str_list: List[str]

class Config:
openapi_extra = {
# "example": {"a": 123},
"examples": {
"Example 01": {
"summary": "An example",
"value": {
"file": "Example-01.jpg",
"str_list": ["a", "b", "c"]
}
},
"Example 02": {
"summary": "Another example",
"value": {
"str_list": ["1", "2", "3"]
}
}
}
}
```

Effect in Redoc:

![](../assets/Snipaste_2023-06-02_11-05-11.png)

## body

```python
class BookBody(BaseModel):
age: int
author: str

class Config:
openapi_extra = {
"description": "This is post RequestBody",
"example": {"age": 12, "author": "author1"},
"examples": {
"example1": {
"summary": "example summary1",
"description": "example description1",
"value": {
"age": 24,
"author": "author2"
}
},
"example2": {
"summary": "example summary2",
"description": "example description2",
"value": {
"age": 48,
"author": "author3"
}
}

}}
```

Effect in swagger:

![](../assets/Snipaste_2023-06-02_11-06-59.png)

## responses

```python
class Message(BaseModel):
message: str = Field(..., description="The message")

class Config:
openapi_extra = {
# "example": {"message": "aaa"},
"examples": {
"example1": {
"summary": "example1 summary",
"value": {
"message": "bbb"
}
},
"example2": {
"summary": "example2 summary",
"value": {
"message": "ccc"
}
}
}
}
```

Effect in swagger:

![](../assets/Snipaste_2023-06-02_11-08-40.png)
12 changes: 12 additions & 0 deletions docs/Tutorial/Operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ def create_book(body: BookBody):

## extra_form

*new in v2.4.0*

!!! Deprecated-Warning warning

`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.

*new in v2.1.0*

Extra form information can be provided using `extra_form` as in the following sample:
Expand All @@ -148,6 +154,12 @@ def create_book(body: BookForm):

## extra_body

*new in v2.4.0*

!!! Deprecated-Warning warning

`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.

*new in v2.1.0*

Extra body information can be provided using `extra_body` as in the following sample:
Expand Down
19 changes: 15 additions & 4 deletions docs/Tutorial/Response.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ class BookResponse(BaseModel):
data: BookBodyWithID


@app.get('/book/<int:bid>', tags=[book_tag], responses={"200": BookResponse})
@app.get('/book/<int:bid>',
tags=[book_tag],
responses={
"200": BookResponse,
# Version 2.4.0 starts supporting response for dictionary types
"201": {"content": {"text/csv": {"schema": {"type": "string"}}}}
})
def get_book(path: BookPath, query: BookBody):
"""get a book
get book by id, age or author
Expand All @@ -26,9 +32,14 @@ def get_book(path: BookPath, query: BookBody):

![image-20210526104627124](../assets/image-20210526104627124.png)


## extra_responses

*New in v2.4.0*

!!! Deprecated-Warning warning

`extra_responses` have been merged into the `responses`, and `extra_responses` will be deprecated in v3.x.

*New in v1.0.0*

You can pass to your path operation decorators a parameter `extra_responses`.
Expand All @@ -43,14 +54,14 @@ Like this:
'/book/<int:bid>',
tags=[book_tag],
responses={"200": BookResponse},
extra_responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}},
extra_responses={"201": {"content": {"text/csv": {"schema": {"type": "string"}}}}},
security=security
)
def get_book(path: BookPath):
...


@api.post('/book', extra_responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
@api.post('/book', extra_responses={"201": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
def create_book(body: BookBody):
...
```
Expand Down
8 changes: 8 additions & 0 deletions docs/Tutorial/Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,14 @@ def endpoint():

You can also use [responses ](./Response.md#responses) and [extra_responses](./Response.md#extra_responses) in your api.

*New in v2.4.0*

!!! Deprecated-Warning warning

`extra_responses` have been merged into the `responses`, and `extra_responses` will be deprecated in v3.x.



## doc_ui

You can pass `doc_ui=False` to disable the `OpenAPI spec` when init `OpenAPI `.
Expand Down
Binary file added docs/assets/Snipaste_2023-06-02_11-05-11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Snipaste_2023-06-02_11-06-59.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Snipaste_2023-06-02_11-08-40.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/api_blueprint_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_book():
return {"code": 0, "message": "ok"}


@api.post('/book', extra_responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
@api.post('/book', responses={"200": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
def create_book(body: BookBody):
assert body.age == 3
return {"code": 0, "message": "ok"}
Expand Down
81 changes: 81 additions & 0 deletions examples/openapi_extra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# @Author : llc
# @Time : 2023/6/1 15:04
from typing import List

from pydantic import BaseModel

from flask_openapi3 import OpenAPI, FileStorage

app = OpenAPI(__name__)


class UploadFilesForm(BaseModel):
file: FileStorage
str_list: List[str]

class Config:
openapi_extra = {
# "example": {"a": 123},
"examples": {
"Example 01": {
"summary": "An example",
"value": {
"file": "Example-01.jpg",
"str_list": ["a", "b", "c"]
}
},
"Example 02": {
"summary": "Another example",
"value": {
"str_list": ["1", "2", "3"]
}
}
}
}


class BookBody(BaseModel):
age: int
author: str

class Config:
openapi_extra = {
"description": "This is post RequestBody",
"example": {"age": 12, "author": "author1"},
"examples": {
"example1": {
"summary": "example summary1",
"description": "example description1",
"value": {
"age": 24,
"author": "author2"
}
},
"example2": {
"summary": "example summary2",
"description": "example description2",
"value": {
"age": 48,
"author": "author3"
}
}

}}


@app.post('/upload/files')
def upload_files(form: UploadFilesForm):
print(form.file)
print(form.str_list)
return {"code": 0, "message": "ok"}


@app.post('/book', )
def create_book(body: BookBody):
print(body)
return {"code": 0, "message": "ok"}


if __name__ == "__main__":
app.run(debug=True)
28 changes: 24 additions & 4 deletions examples/response_demo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# @Author : [martinatseequent](https://github.com/martinatseequent)
# @Author : llc
# @Time : 2021/6/22 9:32

import json
Expand All @@ -11,7 +11,7 @@
from flask_openapi3 import Info
from flask_openapi3 import OpenAPI, APIBlueprint

app = OpenAPI(__name__, info=Info(title="Hello API", version="1.0.0"), )
app = OpenAPI(__name__, info=Info(title="Hello API", version="1.0.0"))

bp = APIBlueprint("Hello BP", __name__)

Expand All @@ -23,8 +23,28 @@ class HelloPath(BaseModel):
class Message(BaseModel):
message: str = Field(..., description="The message")


@bp.get("/hello/<string:name>", responses={"200": Message})
class Config:
openapi_extra = {
# "example": {"message": "aaa"},
"examples": {
"example1": {
"summary": "example1 summary",
"value": {
"message": "bbb"
}
},
"example2": {
"summary": "example2 summary",
"value": {
"message": "ccc"
}
}
}
}


@bp.get("/hello/<string:name>",
responses={"200": Message, "201": {"content": {"text/csv": {"schema": {"type": "string"}}}}})
def hello(path: HelloPath):
message = {"message": f"""Hello {path.name}!"""}

Expand Down
Loading

0 comments on commit 1c51e53

Please sign in to comment.