增加环绕侦察场景适配

This commit is contained in:
2026-01-08 15:44:38 +08:00
parent 3eba1f962b
commit 10c5bb5a8a
5441 changed files with 40219 additions and 379695 deletions

View File

@@ -1,13 +1,12 @@
import json
from typing import Any, Dict, Optional
from typing import Annotated, Any, Optional
from annotated_doc import Doc
from fastapi.encoders import jsonable_encoder
from starlette.responses import HTMLResponse
from typing_extensions import Annotated
swagger_ui_default_parameters: Annotated[
Dict[str, Any],
dict[str, Any],
Doc(
"""
Default configurations for Swagger UI.
@@ -82,7 +81,7 @@ def get_swagger_ui_html(
),
] = None,
init_oauth: Annotated[
Optional[Dict[str, Any]],
Optional[dict[str, Any]],
Doc(
"""
A dictionary with Swagger UI OAuth2 initialization configurations.
@@ -90,7 +89,7 @@ def get_swagger_ui_html(
),
] = None,
swagger_ui_parameters: Annotated[
Optional[Dict[str, Any]],
Optional[dict[str, Any]],
Doc(
"""
Configuration parameters for Swagger UI.

View File

@@ -1,17 +1,16 @@
from collections.abc import Iterable, Mapping
from enum import Enum
from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Type, Union
from typing import Annotated, Any, Callable, Optional, Union
from fastapi._compat import (
PYDANTIC_V2,
CoreSchema,
GetJsonSchemaHandler,
JsonSchemaValue,
_model_rebuild,
with_info_plain_validator_function,
)
from fastapi._compat import with_info_plain_validator_function
from fastapi.logger import logger
from pydantic import AnyUrl, BaseModel, Field
from typing_extensions import Annotated, Literal, TypedDict
from pydantic import (
AnyUrl,
BaseModel,
Field,
GetJsonSchemaHandler,
)
from typing_extensions import Literal, TypedDict
from typing_extensions import deprecated as typing_deprecated
try:
@@ -44,25 +43,19 @@ except ImportError: # pragma: no cover
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
) -> JsonSchemaValue:
cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler
) -> dict[str, Any]:
return {"type": "string", "format": "email"}
@classmethod
def __get_pydantic_core_schema__(
cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
) -> CoreSchema:
cls, source: type[Any], handler: Callable[[Any], Mapping[str, Any]]
) -> Mapping[str, Any]:
return with_info_plain_validator_function(cls._validate)
class BaseModelWithConfig(BaseModel):
if PYDANTIC_V2:
model_config = {"extra": "allow"}
else:
class Config:
extra = "allow"
model_config = {"extra": "allow"}
class Contact(BaseModelWithConfig):
@@ -88,7 +81,7 @@ class Info(BaseModelWithConfig):
class ServerVariable(BaseModelWithConfig):
enum: Annotated[Optional[List[str]], Field(min_length=1)] = None
enum: Annotated[Optional[list[str]], Field(min_length=1)] = None
default: str
description: Optional[str] = None
@@ -96,7 +89,7 @@ class ServerVariable(BaseModelWithConfig):
class Server(BaseModelWithConfig):
url: Union[AnyUrl, str]
description: Optional[str] = None
variables: Optional[Dict[str, ServerVariable]] = None
variables: Optional[dict[str, ServerVariable]] = None
class Reference(BaseModel):
@@ -105,7 +98,7 @@ class Reference(BaseModel):
class Discriminator(BaseModel):
propertyName: str
mapping: Optional[Dict[str, str]] = None
mapping: Optional[dict[str, str]] = None
class XML(BaseModelWithConfig):
@@ -137,34 +130,34 @@ class Schema(BaseModelWithConfig):
dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor")
ref: Optional[str] = Field(default=None, alias="$ref")
dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef")
defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
defs: Optional[dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
comment: Optional[str] = Field(default=None, alias="$comment")
# Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s
# A Vocabulary for Applying Subschemas
allOf: Optional[List["SchemaOrBool"]] = None
anyOf: Optional[List["SchemaOrBool"]] = None
oneOf: Optional[List["SchemaOrBool"]] = None
allOf: Optional[list["SchemaOrBool"]] = None
anyOf: Optional[list["SchemaOrBool"]] = None
oneOf: Optional[list["SchemaOrBool"]] = None
not_: Optional["SchemaOrBool"] = Field(default=None, alias="not")
if_: Optional["SchemaOrBool"] = Field(default=None, alias="if")
then: Optional["SchemaOrBool"] = None
else_: Optional["SchemaOrBool"] = Field(default=None, alias="else")
dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None
prefixItems: Optional[List["SchemaOrBool"]] = None
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
# items: Optional["SchemaOrBool"] = None
items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None
items: Optional[Union["SchemaOrBool", list["SchemaOrBool"]]] = None
contains: Optional["SchemaOrBool"] = None
properties: Optional[Dict[str, "SchemaOrBool"]] = None
patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None
properties: Optional[dict[str, "SchemaOrBool"]] = None
patternProperties: Optional[dict[str, "SchemaOrBool"]] = None
additionalProperties: Optional["SchemaOrBool"] = None
propertyNames: Optional["SchemaOrBool"] = None
unevaluatedItems: Optional["SchemaOrBool"] = None
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
enum: Optional[List[Any]] = None
type: Optional[Union[SchemaType, list[SchemaType]]] = None
enum: Optional[list[Any]] = None
const: Optional[Any] = None
multipleOf: Optional[float] = Field(default=None, gt=0)
maximum: Optional[float] = None
@@ -181,8 +174,8 @@ class Schema(BaseModelWithConfig):
minContains: Optional[int] = Field(default=None, ge=0)
maxProperties: Optional[int] = Field(default=None, ge=0)
minProperties: Optional[int] = Field(default=None, ge=0)
required: Optional[List[str]] = None
dependentRequired: Optional[Dict[str, Set[str]]] = None
required: Optional[list[str]] = None
dependentRequired: Optional[dict[str, set[str]]] = None
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c
# Vocabularies for Semantic Content With "format"
format: Optional[str] = None
@@ -199,7 +192,7 @@ class Schema(BaseModelWithConfig):
deprecated: Optional[bool] = None
readOnly: Optional[bool] = None
writeOnly: Optional[bool] = None
examples: Optional[List[Any]] = None
examples: Optional[list[Any]] = None
# Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object
# Schema Object
discriminator: Optional[Discriminator] = None
@@ -225,13 +218,7 @@ class Example(TypedDict, total=False):
value: Optional[Any]
externalValue: Optional[AnyUrl]
if PYDANTIC_V2: # type: ignore [misc]
__pydantic_config__ = {"extra": "allow"}
else:
class Config:
extra = "allow"
__pydantic_config__ = {"extra": "allow"} # type: ignore[misc]
class ParameterInType(Enum):
@@ -243,7 +230,7 @@ class ParameterInType(Enum):
class Encoding(BaseModelWithConfig):
contentType: Optional[str] = None
headers: Optional[Dict[str, Union["Header", Reference]]] = None
headers: Optional[dict[str, Union["Header", Reference]]] = None
style: Optional[str] = None
explode: Optional[bool] = None
allowReserved: Optional[bool] = None
@@ -252,8 +239,8 @@ class Encoding(BaseModelWithConfig):
class MediaType(BaseModelWithConfig):
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
examples: Optional[dict[str, Union[Example, Reference]]] = None
encoding: Optional[dict[str, Encoding]] = None
class ParameterBase(BaseModelWithConfig):
@@ -266,9 +253,9 @@ class ParameterBase(BaseModelWithConfig):
allowReserved: Optional[bool] = None
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
example: Optional[Any] = None
examples: Optional[Dict[str, Union[Example, Reference]]] = None
examples: Optional[dict[str, Union[Example, Reference]]] = None
# Serialization rules for more complex scenarios
content: Optional[Dict[str, MediaType]] = None
content: Optional[dict[str, MediaType]] = None
class Parameter(ParameterBase):
@@ -282,14 +269,14 @@ class Header(ParameterBase):
class RequestBody(BaseModelWithConfig):
description: Optional[str] = None
content: Dict[str, MediaType]
content: dict[str, MediaType]
required: Optional[bool] = None
class Link(BaseModelWithConfig):
operationRef: Optional[str] = None
operationId: Optional[str] = None
parameters: Optional[Dict[str, Union[Any, str]]] = None
parameters: Optional[dict[str, Union[Any, str]]] = None
requestBody: Optional[Union[Any, str]] = None
description: Optional[str] = None
server: Optional[Server] = None
@@ -297,25 +284,25 @@ class Link(BaseModelWithConfig):
class Response(BaseModelWithConfig):
description: str
headers: Optional[Dict[str, Union[Header, Reference]]] = None
content: Optional[Dict[str, MediaType]] = None
links: Optional[Dict[str, Union[Link, Reference]]] = None
headers: Optional[dict[str, Union[Header, Reference]]] = None
content: Optional[dict[str, MediaType]] = None
links: Optional[dict[str, Union[Link, Reference]]] = None
class Operation(BaseModelWithConfig):
tags: Optional[List[str]] = None
tags: Optional[list[str]] = None
summary: Optional[str] = None
description: Optional[str] = None
externalDocs: Optional[ExternalDocumentation] = None
operationId: Optional[str] = None
parameters: Optional[List[Union[Parameter, Reference]]] = None
parameters: Optional[list[Union[Parameter, Reference]]] = None
requestBody: Optional[Union[RequestBody, Reference]] = None
# Using Any for Specification Extensions
responses: Optional[Dict[str, Union[Response, Any]]] = None
callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None
responses: Optional[dict[str, Union[Response, Any]]] = None
callbacks: Optional[dict[str, Union[dict[str, "PathItem"], Reference]]] = None
deprecated: Optional[bool] = None
security: Optional[List[Dict[str, List[str]]]] = None
servers: Optional[List[Server]] = None
security: Optional[list[dict[str, list[str]]]] = None
servers: Optional[list[Server]] = None
class PathItem(BaseModelWithConfig):
@@ -330,8 +317,8 @@ class PathItem(BaseModelWithConfig):
head: Optional[Operation] = None
patch: Optional[Operation] = None
trace: Optional[Operation] = None
servers: Optional[List[Server]] = None
parameters: Optional[List[Union[Parameter, Reference]]] = None
servers: Optional[list[Server]] = None
parameters: Optional[list[Union[Parameter, Reference]]] = None
class SecuritySchemeType(Enum):
@@ -370,7 +357,7 @@ class HTTPBearer(HTTPBase):
class OAuthFlow(BaseModelWithConfig):
refreshUrl: Optional[str] = None
scopes: Dict[str, str] = {}
scopes: dict[str, str] = {}
class OAuthFlowImplicit(OAuthFlow):
@@ -413,17 +400,17 @@ SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer]
class Components(BaseModelWithConfig):
schemas: Optional[Dict[str, Union[Schema, Reference]]] = None
responses: Optional[Dict[str, Union[Response, Reference]]] = None
parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None
examples: Optional[Dict[str, Union[Example, Reference]]] = None
requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None
headers: Optional[Dict[str, Union[Header, Reference]]] = None
securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None
links: Optional[Dict[str, Union[Link, Reference]]] = None
schemas: Optional[dict[str, Union[Schema, Reference]]] = None
responses: Optional[dict[str, Union[Response, Reference]]] = None
parameters: Optional[dict[str, Union[Parameter, Reference]]] = None
examples: Optional[dict[str, Union[Example, Reference]]] = None
requestBodies: Optional[dict[str, Union[RequestBody, Reference]]] = None
headers: Optional[dict[str, Union[Header, Reference]]] = None
securitySchemes: Optional[dict[str, Union[SecurityScheme, Reference]]] = None
links: Optional[dict[str, Union[Link, Reference]]] = None
# Using Any for Specification Extensions
callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None
pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None
callbacks: Optional[dict[str, Union[dict[str, PathItem], Reference, Any]]] = None
pathItems: Optional[dict[str, Union[PathItem, Reference]]] = None
class Tag(BaseModelWithConfig):
@@ -436,16 +423,16 @@ class OpenAPI(BaseModelWithConfig):
openapi: str
info: Info
jsonSchemaDialect: Optional[str] = None
servers: Optional[List[Server]] = None
servers: Optional[list[Server]] = None
# Using Any for Specification Extensions
paths: Optional[Dict[str, Union[PathItem, Any]]] = None
webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None
paths: Optional[dict[str, Union[PathItem, Any]]] = None
webhooks: Optional[dict[str, Union[PathItem, Reference]]] = None
components: Optional[Components] = None
security: Optional[List[Dict[str, List[str]]]] = None
tags: Optional[List[Tag]] = None
security: Optional[list[dict[str, list[str]]]] = None
tags: Optional[list[Tag]] = None
externalDocs: Optional[ExternalDocumentation] = None
_model_rebuild(Schema)
_model_rebuild(Operation)
_model_rebuild(Encoding)
Schema.model_rebuild()
Operation.model_rebuild()
Encoding.model_rebuild()

View File

@@ -1,11 +1,11 @@
import http.client
import inspect
import warnings
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
from collections.abc import Sequence
from typing import Any, Optional, Union, cast
from fastapi import routing
from fastapi._compat import (
JsonSchemaValue,
ModelField,
Undefined,
get_compat_model_name_map,
@@ -19,8 +19,10 @@ from fastapi.dependencies.utils import (
_get_flat_fields_from_params,
get_flat_dependant,
get_flat_params,
get_validation_alias,
)
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX
from fastapi.openapi.models import OpenAPI
from fastapi.params import Body, ParamTypes
@@ -36,8 +38,6 @@ from starlette.responses import JSONResponse
from starlette.routing import BaseRoute
from typing_extensions import Literal
from .._compat import _is_model_field
validation_error_definition = {
"title": "ValidationError",
"type": "object",
@@ -65,7 +65,7 @@ validation_error_response_definition = {
},
}
status_code_ranges: Dict[str, str] = {
status_code_ranges: dict[str, str] = {
"1XX": "Information",
"2XX": "Success",
"3XX": "Redirection",
@@ -77,18 +77,27 @@ status_code_ranges: Dict[str, str] = {
def get_openapi_security_definitions(
flat_dependant: Dependant,
) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
security_definitions = {}
operation_security = []
for security_requirement in flat_dependant.security_requirements:
# Use a dict to merge scopes for same security scheme
operation_security_dict: dict[str, list[str]] = {}
for security_dependency in flat_dependant._security_dependencies:
security_definition = jsonable_encoder(
security_requirement.security_scheme.model,
security_dependency._security_scheme.model,
by_alias=True,
exclude_none=True,
)
security_name = security_requirement.security_scheme.scheme_name
security_name = security_dependency._security_scheme.scheme_name
security_definitions[security_name] = security_definition
operation_security.append({security_name: security_requirement.scopes})
# Merge scopes for the same security scheme
if security_name not in operation_security_dict:
operation_security_dict[security_name] = []
for scope in security_dependency.oauth_scopes or []:
if scope not in operation_security_dict[security_name]:
operation_security_dict[security_name].append(scope)
operation_security = [
{name: scopes} for name, scopes in operation_security_dict.items()
]
return security_definitions, operation_security
@@ -96,11 +105,11 @@ def _get_openapi_operation_parameters(
*,
dependant: Dependant,
model_name_map: ModelNameMap,
field_mapping: Dict[
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
field_mapping: dict[
tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any]
],
separate_input_output_schemas: bool = True,
) -> List[Dict[str, Any]]:
) -> 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)
@@ -132,7 +141,7 @@ def _get_openapi_operation_parameters(
field_mapping=field_mapping,
separate_input_output_schemas=separate_input_output_schemas,
)
name = param.alias
name = get_validation_alias(param)
convert_underscores = getattr(
param.field_info,
"convert_underscores",
@@ -140,7 +149,7 @@ def _get_openapi_operation_parameters(
)
if (
param_type == ParamTypes.header
and param.alias == param.name
and name == param.name
and convert_underscores
):
name = param.name.replace("_", "-")
@@ -169,14 +178,14 @@ def get_openapi_operation_request_body(
*,
body_field: Optional[ModelField],
model_name_map: ModelNameMap,
field_mapping: Dict[
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
field_mapping: dict[
tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any]
],
separate_input_output_schemas: bool = True,
) -> Optional[Dict[str, Any]]:
) -> Optional[dict[str, Any]]:
if not body_field:
return None
assert _is_model_field(body_field)
assert isinstance(body_field, ModelField)
body_schema = get_schema_from_model_field(
field=body_field,
model_name_map=model_name_map,
@@ -186,10 +195,10 @@ def get_openapi_operation_request_body(
field_info = cast(Body, body_field.field_info)
request_media_type = field_info.media_type
required = body_field.required
request_body_oai: Dict[str, Any] = {}
request_body_oai: dict[str, Any] = {}
if required:
request_body_oai["required"] = required
request_media_content: Dict[str, Any] = {"schema": body_schema}
request_media_content: dict[str, Any] = {"schema": body_schema}
if field_info.openapi_examples:
request_media_content["examples"] = jsonable_encoder(
field_info.openapi_examples
@@ -204,9 +213,9 @@ def generate_operation_id(
*, route: routing.APIRoute, method: str
) -> str: # pragma: nocover
warnings.warn(
"fastapi.openapi.utils.generate_operation_id() was deprecated, "
message="fastapi.openapi.utils.generate_operation_id() was deprecated, "
"it is not used internally, and will be removed soon",
DeprecationWarning,
category=FastAPIDeprecationWarning,
stacklevel=2,
)
if route.operation_id:
@@ -222,9 +231,9 @@ def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str:
def get_openapi_operation_metadata(
*, route: routing.APIRoute, method: str, operation_ids: Set[str]
) -> Dict[str, Any]:
operation: Dict[str, Any] = {}
*, route: routing.APIRoute, method: str, operation_ids: set[str]
) -> dict[str, Any]:
operation: dict[str, Any] = {}
if route.tags:
operation["tags"] = route.tags
operation["summary"] = generate_operation_summary(route=route, method=method)
@@ -250,19 +259,19 @@ def get_openapi_operation_metadata(
def get_openapi_path(
*,
route: routing.APIRoute,
operation_ids: Set[str],
operation_ids: set[str],
model_name_map: ModelNameMap,
field_mapping: Dict[
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
field_mapping: dict[
tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any]
],
separate_input_output_schemas: bool = True,
) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
path = {}
security_schemes: Dict[str, Any] = {}
definitions: Dict[str, Any] = {}
security_schemes: dict[str, Any] = {}
definitions: dict[str, Any] = {}
assert route.methods is not None, "Methods must be a list"
if isinstance(route.response_class, DefaultPlaceholder):
current_response_class: Type[Response] = route.response_class.value
current_response_class: type[Response] = route.response_class.value
else:
current_response_class = route.response_class
assert current_response_class, "A response class is needed to generate OpenAPI"
@@ -272,7 +281,7 @@ def get_openapi_path(
operation = get_openapi_operation_metadata(
route=route, method=method, operation_ids=operation_ids
)
parameters: List[Dict[str, Any]] = []
parameters: list[dict[str, Any]] = []
flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True)
security_definitions, operation_security = get_openapi_security_definitions(
flat_dependant=flat_dependant
@@ -380,7 +389,7 @@ def get_openapi_path(
"An additional response must be a dict"
)
field = route.response_fields.get(additional_status_code)
additional_field_schema: Optional[Dict[str, Any]] = None
additional_field_schema: Optional[dict[str, Any]] = None
if field:
additional_field_schema = get_schema_from_model_field(
field=field,
@@ -435,17 +444,17 @@ def get_openapi_path(
def get_fields_from_routes(
routes: Sequence[BaseRoute],
) -> List[ModelField]:
body_fields_from_routes: List[ModelField] = []
responses_from_routes: List[ModelField] = []
request_fields_from_routes: List[ModelField] = []
callback_flat_models: List[ModelField] = []
) -> list[ModelField]:
body_fields_from_routes: list[ModelField] = []
responses_from_routes: list[ModelField] = []
request_fields_from_routes: list[ModelField] = []
callback_flat_models: list[ModelField] = []
for route in routes:
if getattr(route, "include_in_schema", None) and isinstance(
route, routing.APIRoute
):
if route.body_field:
assert _is_model_field(route.body_field), (
assert isinstance(route.body_field, ModelField), (
"A request body must be a Pydantic Field"
)
body_fields_from_routes.append(route.body_field)
@@ -473,15 +482,15 @@ def get_openapi(
description: Optional[str] = None,
routes: Sequence[BaseRoute],
webhooks: Optional[Sequence[BaseRoute]] = None,
tags: Optional[List[Dict[str, Any]]] = None,
servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
tags: Optional[list[dict[str, Any]]] = None,
servers: Optional[list[dict[str, Union[str, Any]]]] = None,
terms_of_service: Optional[str] = None,
contact: Optional[Dict[str, Union[str, Any]]] = None,
license_info: Optional[Dict[str, Union[str, Any]]] = None,
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}
external_docs: Optional[dict[str, Any]] = None,
) -> dict[str, Any]:
info: dict[str, Any] = {"title": title, "version": version}
if summary:
info["summary"] = summary
if description:
@@ -492,13 +501,13 @@ def get_openapi(
info["contact"] = contact
if license_info:
info["license"] = license_info
output: Dict[str, Any] = {"openapi": openapi_version, "info": info}
output: dict[str, Any] = {"openapi": openapi_version, "info": info}
if servers:
output["servers"] = servers
components: Dict[str, Dict[str, Any]] = {}
paths: Dict[str, Dict[str, Any]] = {}
webhook_paths: Dict[str, Dict[str, Any]] = {}
operation_ids: Set[str] = set()
components: dict[str, dict[str, Any]] = {}
paths: dict[str, dict[str, Any]] = {}
webhook_paths: dict[str, dict[str, Any]] = {}
operation_ids: set[str] = set()
all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or []))
model_name_map = get_compat_model_name_map(all_fields)
field_mapping, definitions = get_definitions(