6
6
7
7
from openapi_spec_validator .exceptions import (
8
8
ParameterDuplicateError , ExtraParametersError , UnresolvableParameterError ,
9
- OpenAPIValidationError
9
+ OpenAPIValidationError , DuplicateOperationIDError ,
10
10
)
11
11
from openapi_spec_validator .decorators import ValidationErrorWrapper
12
12
from openapi_spec_validator .factories import Draft4ExtendedValidatorFactory
@@ -157,8 +157,10 @@ def _iter_value_errors(self, schema, value):
157
157
158
158
class PathsValidator (object ):
159
159
160
- def __init__ (self , dereferencer ):
160
+ def __init__ (self , dereferencer , operation_ids_registry = None ):
161
161
self .dereferencer = dereferencer
162
+ self .operation_ids_registry = [] if operation_ids_registry is None \
163
+ else operation_ids_registry
162
164
163
165
@wraps_errors
164
166
def iter_errors (self , paths ):
@@ -168,13 +170,17 @@ def iter_errors(self, paths):
168
170
yield err
169
171
170
172
def _iter_path_errors (self , url , path_item ):
171
- return PathValidator (self .dereferencer ).iter_errors (url , path_item )
173
+ return PathValidator (
174
+ self .dereferencer , self .operation_ids_registry ).iter_errors (
175
+ url , path_item )
172
176
173
177
174
178
class PathValidator (object ):
175
179
176
- def __init__ (self , dereferencer ):
180
+ def __init__ (self , dereferencer , operation_ids_registry = None ):
177
181
self .dereferencer = dereferencer
182
+ self .operation_ids_registry = [] if operation_ids_registry is None \
183
+ else operation_ids_registry
178
184
179
185
@wraps_errors
180
186
def iter_errors (self , url , path_item ):
@@ -184,7 +190,9 @@ def iter_errors(self, url, path_item):
184
190
yield err
185
191
186
192
def _iter_path_item_errors (self , url , path_item ):
187
- return PathItemValidator (self .dereferencer ).iter_errors (url , path_item )
193
+ return PathItemValidator (
194
+ self .dereferencer , self .operation_ids_registry ).iter_errors (
195
+ url , path_item )
188
196
189
197
190
198
class PathItemValidator (object ):
@@ -193,8 +201,10 @@ class PathItemValidator(object):
193
201
'get' , 'put' , 'post' , 'delete' , 'options' , 'head' , 'patch' , 'trace' ,
194
202
]
195
203
196
- def __init__ (self , dereferencer ):
204
+ def __init__ (self , dereferencer , operation_ids_registry = None ):
197
205
self .dereferencer = dereferencer
206
+ self .operation_ids_registry = [] if operation_ids_registry is None \
207
+ else operation_ids_registry
198
208
199
209
@wraps_errors
200
210
def iter_errors (self , url , path_item ):
@@ -213,23 +223,33 @@ def iter_errors(self, url, path_item):
213
223
yield err
214
224
215
225
def _iter_operation_errors (self , url , name , operation , path_parameters ):
216
- return OperationValidator (self .dereferencer ).iter_errors (
217
- url , name , operation , path_parameters )
226
+ return OperationValidator (
227
+ self .dereferencer , self .operation_ids_registry ).iter_errors (
228
+ url , name , operation , path_parameters )
218
229
219
230
def _iter_parameters_errors (self , parameters ):
220
231
return ParametersValidator (self .dereferencer ).iter_errors (parameters )
221
232
222
233
223
234
class OperationValidator (object ):
224
235
225
- def __init__ (self , dereferencer ):
236
+ def __init__ (self , dereferencer , seen_ids = None ):
226
237
self .dereferencer = dereferencer
238
+ self .seen_ids = [] if seen_ids is None else seen_ids
227
239
228
240
@wraps_errors
229
241
def iter_errors (self , url , name , operation , path_parameters = None ):
230
242
path_parameters = path_parameters or []
231
243
operation_deref = self .dereferencer .dereference (operation )
232
244
245
+ operation_id = operation_deref .get ('operationId' )
246
+ if operation_id is not None and operation_id in self .seen_ids :
247
+ yield DuplicateOperationIDError (
248
+ "Operation ID '{0}' for '{1}' in '{2}' is not unique" .format (
249
+ operation_id , name , url )
250
+ )
251
+ self .seen_ids .append (operation_id )
252
+
233
253
parameters = operation_deref .get ('parameters' , [])
234
254
for err in self ._iter_parameters_errors (parameters ):
235
255
yield err
0 commit comments