1+ import itertools
12from copy import deepcopy
23from dataclasses import dataclass , field
3- from enum import Enum
44from typing import Any , Dict , Iterator , List , Optional , Set , Tuple , Union
55
66from pydantic import ValidationError
1313from .responses import Response , response_from_data
1414
1515
16- class ParameterLocation (str , Enum ):
17- """The places Parameters can be put when calling an Endpoint"""
18-
19- QUERY = "query"
20- PATH = "path"
21- HEADER = "header"
22- COOKIE = "cookie"
23-
24-
2516def import_string_from_class (class_ : Class , prefix : str = "" ) -> str :
2617 """Create a string which is used to import a reference"""
2718 return f"from { prefix } .{ class_ .module_name } import { class_ .name } "
@@ -217,6 +208,7 @@ def _add_parameters(
217208 * , endpoint : "Endpoint" , data : Union [oai .Operation , oai .PathItem ], schemas : Schemas , config : Config
218209 ) -> Tuple [Union ["Endpoint" , ParseError ], Schemas ]:
219210 endpoint = deepcopy (endpoint )
211+ used_python_names : Dict [str , Tuple [Property , oai .ParameterLocation ]] = {}
220212 if data .parameters is None :
221213 return endpoint , schemas
222214 for param in data .parameters :
@@ -232,18 +224,39 @@ def _add_parameters(
232224 )
233225 if isinstance (prop , ParseError ):
234226 return ParseError (detail = f"cannot parse parameter of endpoint { endpoint .name } " , data = prop .data ), schemas
227+
228+ if prop .python_name in used_python_names :
229+ duplicate , duplicate_location = used_python_names [prop .python_name ]
230+ if duplicate .python_name == prop .python_name : # Existing should be converted too for consistency
231+ duplicate .set_python_name (f"{ duplicate .python_name } _{ duplicate_location } " )
232+ prop .set_python_name (f"{ prop .python_name } _{ param .param_in } " )
233+ else :
234+ used_python_names [prop .python_name ] = (prop , param .param_in )
235+
235236 endpoint .relative_imports .update (prop .get_imports (prefix = "..." ))
236237
237- if param .param_in == ParameterLocation .QUERY :
238+ if param .param_in == oai . ParameterLocation .QUERY :
238239 endpoint .query_parameters .append (prop )
239- elif param .param_in == ParameterLocation .PATH :
240+ elif param .param_in == oai . ParameterLocation .PATH :
240241 endpoint .path_parameters .append (prop )
241- elif param .param_in == ParameterLocation .HEADER :
242+ elif param .param_in == oai . ParameterLocation .HEADER :
242243 endpoint .header_parameters .append (prop )
243- elif param .param_in == ParameterLocation .COOKIE :
244+ elif param .param_in == oai . ParameterLocation .COOKIE :
244245 endpoint .cookie_parameters .append (prop )
245246 else :
246247 return ParseError (data = param , detail = "Parameter must be declared in path or query" ), schemas
248+
249+ name_check = set ()
250+ for prop in itertools .chain (
251+ endpoint .query_parameters , endpoint .path_parameters , endpoint .header_parameters , endpoint .cookie_parameters
252+ ):
253+ if prop .python_name in name_check :
254+ return (
255+ ParseError (data = data , detail = f"Could not reconcile duplicate parameters named { prop .python_name } " ),
256+ schemas ,
257+ )
258+ name_check .add (prop .python_name )
259+
247260 return endpoint , schemas
248261
249262 @staticmethod
0 commit comments