1313
1414_T = TypeVar ("_T" ) # noqa: WPS111
1515
16+ REF_TEMPLATE = "#/components/schemas/{model}"
1617SCHEMA_KEY = "openapi_schema"
1718SWAGGER_HTML_TEMPALTE = """
1819<html lang="en">
@@ -75,12 +76,13 @@ def dummy(_var: annotation.annotation) -> None: # type: ignore
7576 return var == Optional [var ]
7677
7778
78- def _add_route_def ( # noqa: C901, WPS210
79+ def _add_route_def ( # noqa: C901, WPS210, WPS211
7980 openapi_schema : Dict [str , Any ],
8081 route : web .ResourceRoute ,
8182 method : str ,
8283 graph : DependencyGraph ,
8384 extra_openapi : Dict [str , Any ],
85+ extra_openapi_schemas : Dict [str , Any ],
8486) -> None :
8587 route_info : Dict [str , Any ] = {
8688 "description" : inspect .getdoc (graph .target ),
@@ -90,6 +92,9 @@ def _add_route_def( # noqa: C901, WPS210
9092 if route .resource is None : # pragma: no cover
9193 return
9294
95+ if extra_openapi_schemas :
96+ openapi_schema ["components" ]["schemas" ].update (extra_openapi_schemas )
97+
9398 params : Dict [tuple [str , str ], Any ] = {}
9499
95100 def _insert_in_params (data : Dict [str , Any ]) -> None :
@@ -114,9 +119,9 @@ def _insert_in_params(data: Dict[str, Any]) -> None:
114119 ):
115120 input_schema = pydantic .TypeAdapter (
116121 dependency .signature .annotation ,
117- ).json_schema ()
122+ ).json_schema (ref_template = REF_TEMPLATE )
118123 openapi_schema ["components" ]["schemas" ].update (
119- input_schema .pop ("definitions " , {}),
124+ input_schema .pop ("$defs " , {}),
120125 )
121126 route_info ["requestBody" ] = {
122127 "content" : {content_type : {"schema" : input_schema }},
@@ -216,13 +221,19 @@ async def event_handler(app: web.Application) -> None:
216221 "__extra_openapi__" ,
217222 {},
218223 )
224+ extra_schemas = getattr (
225+ route ._handler .original_handler ,
226+ "__extra_openapi_schemas__" ,
227+ {},
228+ )
219229 try :
220230 _add_route_def (
221231 openapi_schema ,
222232 route , # type: ignore
223233 route .method ,
224234 route ._handler .graph ,
225235 extra_openapi = extra_openapi ,
236+ extra_openapi_schemas = extra_schemas ,
226237 )
227238 except Exception as exc : # pragma: no cover
228239 logger .warn (
@@ -234,20 +245,23 @@ async def event_handler(app: web.Application) -> None:
234245 elif isinstance (route ._handler , InjectableViewHandler ):
235246 for key , graph in route ._handler .graph_map .items ():
236247 extra_openapi = getattr (
237- getattr (
238- route ._handler .original_handler ,
239- key ,
240- ),
248+ getattr (route ._handler .original_handler , key ),
241249 "__extra_openapi__" ,
242250 {},
243251 )
252+ extra_schemas = getattr (
253+ getattr (route ._handler .original_handler , key ),
254+ "__extra_openapi_schemas__" ,
255+ {},
256+ )
244257 try :
245258 _add_route_def (
246259 openapi_schema ,
247260 route , # type: ignore
248261 key ,
249262 graph ,
250263 extra_openapi = extra_openapi ,
264+ extra_openapi_schemas = extra_schemas ,
251265 )
252266 except Exception as exc : # pragma: no cover
253267 logger .warn (
@@ -315,16 +329,20 @@ def openapi_response(
315329
316330 def decorator (func : _T ) -> _T :
317331 openapi = getattr (func , "__extra_openapi__" , {})
332+ openapi_schemas = getattr (func , "__extra_openapi_schemas__" , {})
318333 adapter : "pydantic.TypeAdapter[Any]" = pydantic .TypeAdapter (model )
319334 responses = openapi .get ("responses" , {})
320335 status_response = responses .get (status , {})
321336 if not status_response :
322337 status_response ["description" ] = description
323338 status_response ["content" ] = status_response .get ("content" , {})
324- status_response ["content" ][content_type ] = {"schema" : adapter .json_schema ()}
339+ response_schema = adapter .json_schema (ref_template = REF_TEMPLATE )
340+ openapi_schemas .update (response_schema .pop ("$defs" , {}))
341+ status_response ["content" ][content_type ] = {"schema" : response_schema }
325342 responses [status ] = status_response
326343 openapi ["responses" ] = responses
327344 func .__extra_openapi__ = openapi # type: ignore
345+ func .__extra_openapi_schemas__ = openapi_schemas # type: ignore
328346 return func
329347
330348 return decorator
0 commit comments