This commit is contained in:
@@ -3,7 +3,7 @@ from typing import Any, Dict, Optional
|
||||
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from starlette.responses import HTMLResponse
|
||||
from typing_extensions import Annotated, Doc
|
||||
from typing_extensions import Annotated, Doc # type: ignore [attr-defined]
|
||||
|
||||
swagger_ui_default_parameters: Annotated[
|
||||
Dict[str, Any],
|
||||
@@ -53,7 +53,7 @@ def get_swagger_ui_html(
|
||||
It is normally set to a CDN URL.
|
||||
"""
|
||||
),
|
||||
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js",
|
||||
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui-bundle.js",
|
||||
swagger_css_url: Annotated[
|
||||
str,
|
||||
Doc(
|
||||
@@ -63,7 +63,7 @@ def get_swagger_ui_html(
|
||||
It is normally set to a CDN URL.
|
||||
"""
|
||||
),
|
||||
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css",
|
||||
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui.css",
|
||||
swagger_favicon_url: Annotated[
|
||||
str,
|
||||
Doc(
|
||||
@@ -188,7 +188,7 @@ def get_redoc_html(
|
||||
It is normally set to a CDN URL.
|
||||
"""
|
||||
),
|
||||
] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js",
|
||||
] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
|
||||
redoc_favicon_url: Annotated[
|
||||
str,
|
||||
Doc(
|
||||
|
||||
@@ -55,7 +55,11 @@ except ImportError: # pragma: no cover
|
||||
return with_info_plain_validator_function(cls._validate)
|
||||
|
||||
|
||||
class BaseModelWithConfig(BaseModel):
|
||||
class Contact(BaseModel):
|
||||
name: Optional[str] = None
|
||||
url: Optional[AnyUrl] = None
|
||||
email: Optional[EmailStr] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
@@ -65,19 +69,21 @@ class BaseModelWithConfig(BaseModel):
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Contact(BaseModelWithConfig):
|
||||
name: Optional[str] = None
|
||||
url: Optional[AnyUrl] = None
|
||||
email: Optional[EmailStr] = None
|
||||
|
||||
|
||||
class License(BaseModelWithConfig):
|
||||
class License(BaseModel):
|
||||
name: str
|
||||
identifier: Optional[str] = None
|
||||
url: Optional[AnyUrl] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Info(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Info(BaseModel):
|
||||
title: str
|
||||
summary: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
@@ -86,18 +92,42 @@ class Info(BaseModelWithConfig):
|
||||
license: Optional[License] = None
|
||||
version: str
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class ServerVariable(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class ServerVariable(BaseModel):
|
||||
enum: Annotated[Optional[List[str]], Field(min_length=1)] = None
|
||||
default: str
|
||||
description: Optional[str] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Server(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Server(BaseModel):
|
||||
url: Union[AnyUrl, str]
|
||||
description: Optional[str] = None
|
||||
variables: Optional[Dict[str, ServerVariable]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Reference(BaseModel):
|
||||
ref: str = Field(alias="$ref")
|
||||
@@ -108,26 +138,36 @@ class Discriminator(BaseModel):
|
||||
mapping: Optional[Dict[str, str]] = None
|
||||
|
||||
|
||||
class XML(BaseModelWithConfig):
|
||||
class XML(BaseModel):
|
||||
name: Optional[str] = None
|
||||
namespace: Optional[str] = None
|
||||
prefix: Optional[str] = None
|
||||
attribute: Optional[bool] = None
|
||||
wrapped: Optional[bool] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class ExternalDocumentation(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class ExternalDocumentation(BaseModel):
|
||||
description: Optional[str] = None
|
||||
url: AnyUrl
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
# Ref JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation#name-type
|
||||
SchemaType = Literal[
|
||||
"array", "boolean", "integer", "null", "number", "object", "string"
|
||||
]
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Schema(BaseModelWithConfig):
|
||||
class Schema(BaseModel):
|
||||
# Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu
|
||||
# Core Vocabulary
|
||||
schema_: Optional[str] = Field(default=None, alias="$schema")
|
||||
@@ -151,7 +191,7 @@ class Schema(BaseModelWithConfig):
|
||||
dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None
|
||||
prefixItems: Optional[List["SchemaOrBool"]] = None
|
||||
# TODO: uncomment and remove below when deprecating Pydantic v1
|
||||
# It generates a list of schemas for tuples, before prefixItems was available
|
||||
# It generales a list of schemas for tuples, before prefixItems was available
|
||||
# items: Optional["SchemaOrBool"] = None
|
||||
items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None
|
||||
contains: Optional["SchemaOrBool"] = None
|
||||
@@ -163,7 +203,7 @@ class Schema(BaseModelWithConfig):
|
||||
unevaluatedProperties: Optional["SchemaOrBool"] = None
|
||||
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
|
||||
# A Vocabulary for Structural Validation
|
||||
type: Optional[Union[SchemaType, List[SchemaType]]] = None
|
||||
type: Optional[str] = None
|
||||
enum: Optional[List[Any]] = None
|
||||
const: Optional[Any] = None
|
||||
multipleOf: Optional[float] = Field(default=None, gt=0)
|
||||
@@ -213,6 +253,14 @@ class Schema(BaseModelWithConfig):
|
||||
),
|
||||
] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents
|
||||
# A JSON Schema MUST be an object or a boolean.
|
||||
@@ -241,22 +289,38 @@ class ParameterInType(Enum):
|
||||
cookie = "cookie"
|
||||
|
||||
|
||||
class Encoding(BaseModelWithConfig):
|
||||
class Encoding(BaseModel):
|
||||
contentType: Optional[str] = None
|
||||
headers: Optional[Dict[str, Union["Header", Reference]]] = None
|
||||
style: Optional[str] = None
|
||||
explode: Optional[bool] = None
|
||||
allowReserved: Optional[bool] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class MediaType(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class MediaType(BaseModel):
|
||||
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
|
||||
example: Optional[Any] = None
|
||||
examples: Optional[Dict[str, Union[Example, Reference]]] = None
|
||||
encoding: Optional[Dict[str, Encoding]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class ParameterBase(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class ParameterBase(BaseModel):
|
||||
description: Optional[str] = None
|
||||
required: Optional[bool] = None
|
||||
deprecated: Optional[bool] = None
|
||||
@@ -270,6 +334,14 @@ class ParameterBase(BaseModelWithConfig):
|
||||
# Serialization rules for more complex scenarios
|
||||
content: Optional[Dict[str, MediaType]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Parameter(ParameterBase):
|
||||
name: str
|
||||
@@ -280,13 +352,21 @@ class Header(ParameterBase):
|
||||
pass
|
||||
|
||||
|
||||
class RequestBody(BaseModelWithConfig):
|
||||
class RequestBody(BaseModel):
|
||||
description: Optional[str] = None
|
||||
content: Dict[str, MediaType]
|
||||
required: Optional[bool] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Link(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Link(BaseModel):
|
||||
operationRef: Optional[str] = None
|
||||
operationId: Optional[str] = None
|
||||
parameters: Optional[Dict[str, Union[Any, str]]] = None
|
||||
@@ -294,15 +374,31 @@ class Link(BaseModelWithConfig):
|
||||
description: Optional[str] = None
|
||||
server: Optional[Server] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Response(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Response(BaseModel):
|
||||
description: str
|
||||
headers: Optional[Dict[str, Union[Header, Reference]]] = None
|
||||
content: Optional[Dict[str, MediaType]] = None
|
||||
links: Optional[Dict[str, Union[Link, Reference]]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Operation(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Operation(BaseModel):
|
||||
tags: Optional[List[str]] = None
|
||||
summary: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
@@ -317,8 +413,16 @@ class Operation(BaseModelWithConfig):
|
||||
security: Optional[List[Dict[str, List[str]]]] = None
|
||||
servers: Optional[List[Server]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class PathItem(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class PathItem(BaseModel):
|
||||
ref: Optional[str] = Field(default=None, alias="$ref")
|
||||
summary: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
@@ -333,6 +437,14 @@ class PathItem(BaseModelWithConfig):
|
||||
servers: Optional[List[Server]] = None
|
||||
parameters: Optional[List[Union[Parameter, Reference]]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class SecuritySchemeType(Enum):
|
||||
apiKey = "apiKey"
|
||||
@@ -341,10 +453,18 @@ class SecuritySchemeType(Enum):
|
||||
openIdConnect = "openIdConnect"
|
||||
|
||||
|
||||
class SecurityBase(BaseModelWithConfig):
|
||||
class SecurityBase(BaseModel):
|
||||
type_: SecuritySchemeType = Field(alias="type")
|
||||
description: Optional[str] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class APIKeyIn(Enum):
|
||||
query = "query"
|
||||
@@ -368,10 +488,18 @@ class HTTPBearer(HTTPBase):
|
||||
bearerFormat: Optional[str] = None
|
||||
|
||||
|
||||
class OAuthFlow(BaseModelWithConfig):
|
||||
class OAuthFlow(BaseModel):
|
||||
refreshUrl: Optional[str] = None
|
||||
scopes: Dict[str, str] = {}
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class OAuthFlowImplicit(OAuthFlow):
|
||||
authorizationUrl: str
|
||||
@@ -390,12 +518,20 @@ class OAuthFlowAuthorizationCode(OAuthFlow):
|
||||
tokenUrl: str
|
||||
|
||||
|
||||
class OAuthFlows(BaseModelWithConfig):
|
||||
class OAuthFlows(BaseModel):
|
||||
implicit: Optional[OAuthFlowImplicit] = None
|
||||
password: Optional[OAuthFlowPassword] = None
|
||||
clientCredentials: Optional[OAuthFlowClientCredentials] = None
|
||||
authorizationCode: Optional[OAuthFlowAuthorizationCode] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class OAuth2(SecurityBase):
|
||||
type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type")
|
||||
@@ -412,7 +548,7 @@ class OpenIdConnect(SecurityBase):
|
||||
SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer]
|
||||
|
||||
|
||||
class Components(BaseModelWithConfig):
|
||||
class Components(BaseModel):
|
||||
schemas: Optional[Dict[str, Union[Schema, Reference]]] = None
|
||||
responses: Optional[Dict[str, Union[Response, Reference]]] = None
|
||||
parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None
|
||||
@@ -425,14 +561,30 @@ class Components(BaseModelWithConfig):
|
||||
callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None
|
||||
pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class Tag(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Tag(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
externalDocs: Optional[ExternalDocumentation] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
class OpenAPI(BaseModelWithConfig):
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class OpenAPI(BaseModel):
|
||||
openapi: str
|
||||
info: Info
|
||||
jsonSchemaDialect: Optional[str] = None
|
||||
@@ -445,6 +597,14 @@ class OpenAPI(BaseModelWithConfig):
|
||||
tags: Optional[List[Tag]] = None
|
||||
externalDocs: Optional[ExternalDocumentation] = None
|
||||
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
else:
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
_model_rebuild(Schema)
|
||||
_model_rebuild(Operation)
|
||||
|
||||
@@ -16,15 +16,11 @@ from fastapi._compat import (
|
||||
)
|
||||
from fastapi.datastructures import DefaultPlaceholder
|
||||
from fastapi.dependencies.models import Dependant
|
||||
from fastapi.dependencies.utils import (
|
||||
_get_flat_fields_from_params,
|
||||
get_flat_dependant,
|
||||
get_flat_params,
|
||||
)
|
||||
from fastapi.dependencies.utils import get_flat_dependant, get_flat_params
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX, REF_TEMPLATE
|
||||
from fastapi.openapi.models import OpenAPI
|
||||
from fastapi.params import Body, ParamTypes
|
||||
from fastapi.params import Body, Param
|
||||
from fastapi.responses import Response
|
||||
from fastapi.types import ModelNameMap
|
||||
from fastapi.utils import (
|
||||
@@ -32,9 +28,9 @@ from fastapi.utils import (
|
||||
generate_operation_id_for_path,
|
||||
is_body_allowed_for_status_code,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import BaseRoute
|
||||
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
|
||||
from typing_extensions import Literal
|
||||
|
||||
validation_error_definition = {
|
||||
@@ -91,9 +87,9 @@ def get_openapi_security_definitions(
|
||||
return security_definitions, operation_security
|
||||
|
||||
|
||||
def _get_openapi_operation_parameters(
|
||||
def get_openapi_operation_parameters(
|
||||
*,
|
||||
dependant: Dependant,
|
||||
all_route_params: Sequence[ModelField],
|
||||
schema_generator: GenerateJsonSchema,
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
@@ -102,67 +98,33 @@ def _get_openapi_operation_parameters(
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> List[Dict[str, Any]]:
|
||||
parameters = []
|
||||
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
|
||||
path_params = _get_flat_fields_from_params(flat_dependant.path_params)
|
||||
query_params = _get_flat_fields_from_params(flat_dependant.query_params)
|
||||
header_params = _get_flat_fields_from_params(flat_dependant.header_params)
|
||||
cookie_params = _get_flat_fields_from_params(flat_dependant.cookie_params)
|
||||
parameter_groups = [
|
||||
(ParamTypes.path, path_params),
|
||||
(ParamTypes.query, query_params),
|
||||
(ParamTypes.header, header_params),
|
||||
(ParamTypes.cookie, cookie_params),
|
||||
]
|
||||
default_convert_underscores = True
|
||||
if len(flat_dependant.header_params) == 1:
|
||||
first_field = flat_dependant.header_params[0]
|
||||
if lenient_issubclass(first_field.type_, BaseModel):
|
||||
default_convert_underscores = getattr(
|
||||
first_field.field_info, "convert_underscores", True
|
||||
)
|
||||
for param_type, param_group in parameter_groups:
|
||||
for param in param_group:
|
||||
field_info = param.field_info
|
||||
# field_info = cast(Param, field_info)
|
||||
if not getattr(field_info, "include_in_schema", True):
|
||||
continue
|
||||
param_schema = get_schema_from_model_field(
|
||||
field=param,
|
||||
schema_generator=schema_generator,
|
||||
model_name_map=model_name_map,
|
||||
field_mapping=field_mapping,
|
||||
separate_input_output_schemas=separate_input_output_schemas,
|
||||
)
|
||||
name = param.alias
|
||||
convert_underscores = getattr(
|
||||
param.field_info,
|
||||
"convert_underscores",
|
||||
default_convert_underscores,
|
||||
)
|
||||
if (
|
||||
param_type == ParamTypes.header
|
||||
and param.alias == param.name
|
||||
and convert_underscores
|
||||
):
|
||||
name = param.name.replace("_", "-")
|
||||
|
||||
parameter = {
|
||||
"name": name,
|
||||
"in": param_type.value,
|
||||
"required": param.required,
|
||||
"schema": param_schema,
|
||||
}
|
||||
if field_info.description:
|
||||
parameter["description"] = field_info.description
|
||||
openapi_examples = getattr(field_info, "openapi_examples", None)
|
||||
example = getattr(field_info, "example", None)
|
||||
if openapi_examples:
|
||||
parameter["examples"] = jsonable_encoder(openapi_examples)
|
||||
elif example != Undefined:
|
||||
parameter["example"] = jsonable_encoder(example)
|
||||
if getattr(field_info, "deprecated", None):
|
||||
parameter["deprecated"] = True
|
||||
parameters.append(parameter)
|
||||
for param in all_route_params:
|
||||
field_info = param.field_info
|
||||
field_info = cast(Param, field_info)
|
||||
if not field_info.include_in_schema:
|
||||
continue
|
||||
param_schema = get_schema_from_model_field(
|
||||
field=param,
|
||||
schema_generator=schema_generator,
|
||||
model_name_map=model_name_map,
|
||||
field_mapping=field_mapping,
|
||||
separate_input_output_schemas=separate_input_output_schemas,
|
||||
)
|
||||
parameter = {
|
||||
"name": param.alias,
|
||||
"in": field_info.in_.value,
|
||||
"required": param.required,
|
||||
"schema": param_schema,
|
||||
}
|
||||
if field_info.description:
|
||||
parameter["description"] = field_info.description
|
||||
if field_info.openapi_examples:
|
||||
parameter["examples"] = jsonable_encoder(field_info.openapi_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)
|
||||
return parameters
|
||||
|
||||
|
||||
@@ -285,8 +247,9 @@ def get_openapi_path(
|
||||
operation.setdefault("security", []).extend(operation_security)
|
||||
if security_definitions:
|
||||
security_schemes.update(security_definitions)
|
||||
operation_parameters = _get_openapi_operation_parameters(
|
||||
dependant=route.dependant,
|
||||
all_route_params = get_flat_params(route.dependant)
|
||||
operation_parameters = get_openapi_operation_parameters(
|
||||
all_route_params=all_route_params,
|
||||
schema_generator=schema_generator,
|
||||
model_name_map=model_name_map,
|
||||
field_mapping=field_mapping,
|
||||
@@ -384,9 +347,9 @@ def get_openapi_path(
|
||||
openapi_response = operation_responses.setdefault(
|
||||
status_code_key, {}
|
||||
)
|
||||
assert isinstance(process_response, dict), (
|
||||
"An additional response must be a dict"
|
||||
)
|
||||
assert isinstance(
|
||||
process_response, dict
|
||||
), "An additional response must be a dict"
|
||||
field = route.response_fields.get(additional_status_code)
|
||||
additional_field_schema: Optional[Dict[str, Any]] = None
|
||||
if field:
|
||||
@@ -415,8 +378,7 @@ def get_openapi_path(
|
||||
)
|
||||
deep_dict_update(openapi_response, process_response)
|
||||
openapi_response["description"] = description
|
||||
http422 = "422"
|
||||
all_route_params = get_flat_params(route.dependant)
|
||||
http422 = str(HTTP_422_UNPROCESSABLE_ENTITY)
|
||||
if (all_route_params or route.body_field) and not any(
|
||||
status in operation["responses"]
|
||||
for status in [http422, "4XX", "default"]
|
||||
@@ -454,9 +416,9 @@ def get_fields_from_routes(
|
||||
route, routing.APIRoute
|
||||
):
|
||||
if route.body_field:
|
||||
assert isinstance(route.body_field, ModelField), (
|
||||
"A request body must be a Pydantic Field"
|
||||
)
|
||||
assert isinstance(
|
||||
route.body_field, ModelField
|
||||
), "A request body must be a Pydantic Field"
|
||||
body_fields_from_routes.append(route.body_field)
|
||||
if route.response_field:
|
||||
responses_from_routes.append(route.response_field)
|
||||
@@ -488,7 +450,6 @@ def get_openapi(
|
||||
contact: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
license_info: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
separate_input_output_schemas: bool = True,
|
||||
external_docs: Optional[Dict[str, Any]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
info: Dict[str, Any] = {"title": title, "version": version}
|
||||
if summary:
|
||||
@@ -566,6 +527,4 @@ def get_openapi(
|
||||
output["webhooks"] = webhook_paths
|
||||
if tags:
|
||||
output["tags"] = tags
|
||||
if external_docs:
|
||||
output["externalDocs"] = external_docs
|
||||
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore
|
||||
|
||||
Reference in New Issue
Block a user