Skip to content

Commit

Permalink
BaseModel Config support openapi_extra
Browse files Browse the repository at this point in the history
  • Loading branch information
luolingchun committed Jun 1, 2023
1 parent 035c127 commit f4e4b1b
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 97 deletions.
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)
21 changes: 20 additions & 1 deletion 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 @@ -23,6 +23,25 @@ class HelloPath(BaseModel):
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"
}
}
}
}


@bp.get("/hello/<string:name>", responses={"200": Message})
def hello(path: HelloPath):
Expand Down
29 changes: 2 additions & 27 deletions examples/rest_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import BaseModel, Field

from flask_openapi3 import ExternalDocumentation, ExtraRequestBody, Example
from flask_openapi3 import ExternalDocumentation
from flask_openapi3 import Info, Tag, Server
from flask_openapi3 import OpenAPI

Expand Down Expand Up @@ -128,32 +128,7 @@ def get_books(query: BookQuery):
}


extra_body = ExtraRequestBody(
description="This is post RequestBody",
required=True,
example="ttt",
examples={
"example1": Example(
summary="example summary1",
description="example description1",
value={
"age": 24,
"author": "author1"
}
),
"example2": Example(
summary="example summary2",
description="example description2",
value={
"age": 48,
"author": "author2"
}
)
}
)


@app.post('/book', tags=[book_tag], responses={"200": BookResponse}, extra_body=extra_body)
@app.post('/book', tags=[book_tag], responses={"200": BookResponse})
def create_book(body: BookBody):
print(body)
return {"code": 0, "message": "ok"}, HTTPStatus.OK
Expand Down
13 changes: 2 additions & 11 deletions examples/upload_file_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

from pydantic import BaseModel, Field

from flask_openapi3 import OpenAPI, FileStorage, ExtraRequestBody
from flask_openapi3 import Encoding
from flask_openapi3 import OpenAPI, FileStorage

app = OpenAPI(__name__)

Expand All @@ -23,14 +22,6 @@ class UploadFilesForm(BaseModel):
int_list: List[int]


extra_form = ExtraRequestBody(
description="This is form RequestBody",
required=True,
# replace style (default to form)
encoding={"str_list": Encoding(style="simple")}
)


@app.post('/upload/file')
def upload_file(form: UploadFileForm):
print(form.file.filename)
Expand All @@ -39,7 +30,7 @@ def upload_file(form: UploadFileForm):
return {"code": 0, "message": "ok"}


@app.post('/upload/files', extra_form=extra_form)
@app.post('/upload/files')
def upload_files(form: UploadFilesForm):
print(form.files)
print(form.str_list)
Expand Down
44 changes: 44 additions & 0 deletions flask_openapi3/scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import functools
import inspect
import sys
import warnings
from abc import ABC
from functools import wraps
from typing import Callable, List, Optional, Dict, Type, Any, Tuple
Expand Down Expand Up @@ -31,6 +32,8 @@ def iscoroutinefunction(func: Any) -> bool:

return inspect.iscoroutinefunction(func)

warnings.simplefilter("once")


class APIScaffold(Scaffold, ABC):
def _do_decorator(
Expand Down Expand Up @@ -174,6 +177,15 @@ def get(
doc_ui: Add openapi document UI(swagger, rapidoc and redoc). Defaults to True.
"""

if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

def decorator(func) -> Callable:
header, cookie, path, query, form, body = \
self._do_decorator(
Expand Down Expand Up @@ -245,6 +257,14 @@ def post(
openapi_extensions: Allows extensions to the OpenAPI Schema.
doc_ui: Declares this operation to be shown.
"""
if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

def decorator(func) -> Callable:
header, cookie, path, query, form, body = \
Expand Down Expand Up @@ -317,6 +337,14 @@ def put(
openapi_extensions: Allows extensions to the OpenAPI Schema.
doc_ui: Declares this operation to be shown.
"""
if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

def decorator(func) -> Callable:
header, cookie, path, query, form, body = \
Expand Down Expand Up @@ -389,6 +417,14 @@ def delete(
openapi_extensions: Allows extensions to the OpenAPI Schema.
doc_ui: Declares this operation to be shown.
"""
if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

def decorator(func) -> Callable:
header, cookie, path, query, form, body = \
Expand Down Expand Up @@ -461,6 +497,14 @@ def patch(
openapi_extensions: Allows extensions to the OpenAPI Schema.
doc_ui: Declares this operation to be shown.
"""
if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

def decorator(func) -> Callable:
header, cookie, path, query, form, body = \
Expand Down
24 changes: 24 additions & 0 deletions flask_openapi3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@ def get_responses(
)
}
)

model_config = response.Config
if hasattr(model_config, "openapi_extra"):
_responses[key].description = model_config.openapi_extra.get("description")
_responses[key].headers = model_config.openapi_extra.get("headers")
_responses[key].links = model_config.openapi_extra.get("links")
_content = _responses[key].content
_content["application/json"].example = model_config.openapi_extra.get("example") # type: ignore
_content["application/json"].examples = model_config.openapi_extra.get("examples") # type: ignore
_content["application/json"].encoding = model_config.openapi_extra.get("encoding") # type: ignore

_schemas[response.__name__] = Schema(**schema)
definitions = schema.get("definitions")
if definitions:
Expand Down Expand Up @@ -407,6 +418,13 @@ def parse_parameters(
request_body = RequestBody(**{
"content": _content,
})
model_config = form.Config
if hasattr(model_config, "openapi_extra"):
request_body.description = model_config.openapi_extra.get("description")
request_body.content["multipart/form-data"].example = model_config.openapi_extra.get("example")
request_body.content["multipart/form-data"].examples = model_config.openapi_extra.get("examples")
if model_config.openapi_extra.get("encoding"):
request_body.content["multipart/form-data"].encoding = model_config.openapi_extra.get("encoding")
operation.requestBody = request_body
if body:
_content, _components_schemas = parse_body(body, extra_body)
Expand All @@ -419,6 +437,12 @@ def parse_parameters(
)
else:
request_body = RequestBody(content=_content)
model_config = body.Config
if hasattr(model_config, "openapi_extra"):
request_body.description = model_config.openapi_extra.get("description")
request_body.content["application/json"].example = model_config.openapi_extra.get("example")
request_body.content["application/json"].examples = model_config.openapi_extra.get("examples")
request_body.content["application/json"].encoding = model_config.openapi_extra.get("encoding")
operation.requestBody = request_body
operation.parameters = parameters if parameters else None

Expand Down
12 changes: 12 additions & 0 deletions flask_openapi3/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# @Time : 2022/10/14 16:09
import re
import typing
import warnings

if typing.TYPE_CHECKING:
from .openapi import OpenAPI
Expand All @@ -19,6 +20,8 @@
from .utils import get_operation, parse_and_store_tags, parse_parameters, get_responses, parse_method, \
get_operation_id_for_path

warnings.simplefilter("once")


class APIView:
def __init__(
Expand Down Expand Up @@ -135,6 +138,15 @@ def doc(
doc_ui: Add openapi document UI(swagger, rapidoc and redoc). Defaults to True.
"""

if extra_form is not None:
warnings.warn(
"""`extra_form` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)
if extra_body is not None:
warnings.warn(
"""`extra_body` will be deprecated in v3.x, please use `openapi_extra` instead.""",
DeprecationWarning)

if responses is None:
responses = {}
if extra_responses is None:
Expand Down
Loading

0 comments on commit f4e4b1b

Please sign in to comment.