3030 Body ,
3131 Cookie ,
3232 Header ,
33+ PathParam ,
3334 QueryParam ,
3435 RouteDef ,
3536 SecurityRequirement ,
3637 TypeAnnotation ,
3738)
3839from openapify .core .openapi import models as openapi
40+ from openapify .core .openapi .models import Parameter
3941from openapify .plugin import BasePlugin
4042
4143BASE_PLUGINS = (BodyBinaryPlugin (), GuessMediaTypePlugin (), BaseSchemaPlugin ())
@@ -120,7 +122,11 @@ def _process_route(self, route: RouteDef) -> None:
120122 operation_id = None
121123 external_docs = None
122124 security = None
123- parameters = route .parameters .copy () if route .parameters else []
125+ parameters : list [Parameter ] = []
126+ route_path_params = {
127+ param .name : param
128+ for param in self ._build_path_params (route .path_params or {})
129+ }
124130 request_body : Optional [openapi .RequestBody ] = None
125131 for args_type , args in meta :
126132 if args_type == "request" :
@@ -152,6 +158,11 @@ def _process_route(self, route: RouteDef) -> None:
152158 query_params = args .get ("query_params" )
153159 if query_params :
154160 parameters .extend (self ._build_query_params (query_params ))
161+ path_params = args .get ("path_params" )
162+ if path_params :
163+ for new_param in self ._build_path_params (path_params ):
164+ route_path_params .pop (new_param .name , None )
165+ parameters .append (new_param )
155166 headers = args .get ("headers" )
156167 if headers :
157168 parameters .extend (self ._build_request_headers (headers ))
@@ -176,6 +187,7 @@ def _process_route(self, route: RouteDef) -> None:
176187 security = self ._build_security_requirements (
177188 args .get ("requirements" )
178189 )
190+ parameters .extend (route_path_params .values ())
179191 self .spec .path (
180192 route .path ,
181193 operations = {
@@ -227,6 +239,31 @@ def _build_query_params(
227239 )
228240 return result
229241
242+ def _build_path_params (
243+ self , path_params : Mapping [str , Union [Type , PathParam ]]
244+ ) -> Sequence [openapi .Parameter ]:
245+ result = []
246+ for name , param in path_params .items ():
247+ if not isinstance (param , PathParam ):
248+ param = PathParam (param )
249+ parameter_schema = self .__build_object_schema_with_plugins (
250+ param , name
251+ )
252+ if parameter_schema is None :
253+ parameter_schema = {}
254+ result .append (
255+ openapi .Parameter (
256+ name = name ,
257+ location = openapi .ParameterLocation .PATH ,
258+ description = param .description ,
259+ required = True ,
260+ schema = parameter_schema ,
261+ example = param .example ,
262+ examples = self ._build_examples (param .examples ),
263+ )
264+ )
265+ return result
266+
230267 def _build_request_headers (
231268 self , headers : Dict [str , Union [str , Header ]]
232269 ) -> Sequence [openapi .Parameter ]:
@@ -404,7 +441,7 @@ def _update_responses(
404441
405442 @staticmethod
406443 def _build_external_docs (
407- data : Union [str , Tuple [str , str ]]
444+ data : Union [str , Tuple [str , str ]],
408445 ) -> Optional [openapi .ExternalDocumentation ]:
409446 if not data :
410447 return None
@@ -450,7 +487,7 @@ def _build_examples(
450487
451488 def __build_object_schema_with_plugins (
452489 self ,
453- obj : Union [Body , Cookie , Header , QueryParam ],
490+ obj : Union [Body , Cookie , Header , QueryParam , PathParam ],
454491 name : Optional [str ] = None ,
455492 ) -> Optional [Dict [str , Any ]]:
456493 return build_object_schema_with_plugins (obj , self .plugins , name )
@@ -469,7 +506,7 @@ def _determine_body_media_type(
469506
470507
471508def build_object_schema_with_plugins (
472- obj : Union [Body , Cookie , Header , QueryParam ],
509+ obj : Union [Body , Cookie , Header , QueryParam , PathParam ],
473510 plugins : Sequence [BasePlugin ],
474511 name : Optional [str ] = None ,
475512) -> Optional [Dict [str , Any ]]:
0 commit comments