1
+ import itertools
1
2
from copy import deepcopy
2
3
from dataclasses import dataclass , field
3
- from enum import Enum
4
4
from typing import Any , Dict , Iterator , List , Optional , Set , Tuple , Union
5
5
6
6
from pydantic import ValidationError
13
13
from .responses import Response , response_from_data
14
14
15
15
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
-
25
16
def import_string_from_class (class_ : Class , prefix : str = "" ) -> str :
26
17
"""Create a string which is used to import a reference"""
27
18
return f"from { prefix } .{ class_ .module_name } import { class_ .name } "
@@ -217,6 +208,7 @@ def _add_parameters(
217
208
* , endpoint : "Endpoint" , data : Union [oai .Operation , oai .PathItem ], schemas : Schemas , config : Config
218
209
) -> Tuple [Union ["Endpoint" , ParseError ], Schemas ]:
219
210
endpoint = deepcopy (endpoint )
211
+ used_python_names : Dict [str , Tuple [Property , oai .ParameterLocation ]] = {}
220
212
if data .parameters is None :
221
213
return endpoint , schemas
222
214
for param in data .parameters :
@@ -232,18 +224,39 @@ def _add_parameters(
232
224
)
233
225
if isinstance (prop , ParseError ):
234
226
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
+
235
236
endpoint .relative_imports .update (prop .get_imports (prefix = "..." ))
236
237
237
- if param .param_in == ParameterLocation .QUERY :
238
+ if param .param_in == oai . ParameterLocation .QUERY :
238
239
endpoint .query_parameters .append (prop )
239
- elif param .param_in == ParameterLocation .PATH :
240
+ elif param .param_in == oai . ParameterLocation .PATH :
240
241
endpoint .path_parameters .append (prop )
241
- elif param .param_in == ParameterLocation .HEADER :
242
+ elif param .param_in == oai . ParameterLocation .HEADER :
242
243
endpoint .header_parameters .append (prop )
243
- elif param .param_in == ParameterLocation .COOKIE :
244
+ elif param .param_in == oai . ParameterLocation .COOKIE :
244
245
endpoint .cookie_parameters .append (prop )
245
246
else :
246
247
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
+
247
260
return endpoint , schemas
248
261
249
262
@staticmethod
0 commit comments