Skip to content

Commit 87e393c

Browse files
authored
Merge pull request #35 from p1c2u/fix/validate-default-values
Validate default values
2 parents 548cbff + 2d7a32c commit 87e393c

File tree

2 files changed

+100
-2
lines changed

2 files changed

+100
-2
lines changed

openapi_spec_validator/validators.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from openapi_spec_validator.exceptions import (
88
ParameterDuplicateError, ExtraParametersError, UnresolvableParameterError,
99
)
10+
from openapi_spec_validator.factories import Draft4ExtendedValidatorFactory
1011
from openapi_spec_validator.managers import ResolverManager
1112

1213
log = logging.getLogger(__name__)
@@ -99,10 +100,10 @@ def __init__(self, dereferencer):
99100
def iter_errors(self, schemas):
100101
schemas_deref = self.dereferencer.dereference(schemas)
101102
for name, schema in iteritems(schemas_deref):
102-
for err in self._iter_schem_errors(schema):
103+
for err in self._iter_schema_errors(schema):
103104
yield err
104105

105-
def _iter_schem_errors(self, schema):
106+
def _iter_schema_errors(self, schema):
106107
return SchemaValidator(self.dereferencer).iter_errors(schema)
107108

108109

@@ -132,6 +133,19 @@ def iter_errors(self, schema, require_properties=True):
132133
)
133134
)
134135

136+
if 'default' in schema_deref:
137+
default = schema_deref['default']
138+
nullable = schema_deref.get('nullable', False)
139+
if default is not None or nullable is not True:
140+
for err in self._iter_value_errors(schema_deref, default):
141+
yield err
142+
143+
def _iter_value_errors(self, schema, value):
144+
resolver = RefResolver.from_schema(schema)
145+
validator = Draft4ExtendedValidatorFactory.from_resolver(resolver)
146+
for err in validator(schema, resolver=resolver).iter_errors(value):
147+
yield err
148+
135149

136150
class PathsValidator(object):
137151

@@ -245,9 +259,31 @@ def iter_errors(self, parameters):
245259
seen = set()
246260
for parameter in parameters:
247261
parameter_deref = self.dereferencer.dereference(parameter)
262+
for err in self._iter_parameter_errors(parameter_deref):
263+
yield err
264+
248265
key = (parameter_deref['name'], parameter_deref['in'])
249266
if key in seen:
250267
yield ParameterDuplicateError(
251268
"Duplicate parameter `{0}`".format(parameter_deref['name'])
252269
)
253270
seen.add(key)
271+
272+
def _iter_parameter_errors(self, parameter):
273+
return ParameterValidator(self.dereferencer).iter_errors(parameter)
274+
275+
276+
class ParameterValidator(object):
277+
278+
def __init__(self, dereferencer):
279+
self.dereferencer = dereferencer
280+
281+
def iter_errors(self, parameter):
282+
if 'schema' in parameter:
283+
schema = parameter['schema']
284+
schema_deref = self.dereferencer.dereference(schema)
285+
for err in self._iter_schema_errors(schema_deref):
286+
yield err
287+
288+
def _iter_schema_errors(self, schema):
289+
return SchemaValidator(self.dereferencer).iter_errors(schema)

tests/integration/test_validators.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,65 @@ def test_undocumented_parameter(self, validator):
177177
"Path parameter 'param2' for 'get' operation in "
178178
"'/test/{param1}/{param2}' was not resolved"
179179
)
180+
181+
def test_default_value_wrong_type(self, validator):
182+
spec = {
183+
'openapi': '3.0.0',
184+
'info': {
185+
'title': 'Test Api',
186+
'version': '0.0.1',
187+
},
188+
'paths': {},
189+
'components': {
190+
'schemas': {
191+
'test': {
192+
'type': 'integer',
193+
'default': 'invaldtype',
194+
},
195+
},
196+
},
197+
}
198+
199+
errors = validator.iter_errors(spec)
200+
201+
errors_list = list(errors)
202+
assert len(errors_list) == 1
203+
assert errors_list[0].__class__ == ValidationError
204+
assert errors_list[0].message == (
205+
"'invaldtype' is not of type 'integer'"
206+
)
207+
208+
def test_parameter_default_value_wrong_type(self, validator):
209+
spec = {
210+
'openapi': '3.0.0',
211+
'info': {
212+
'title': 'Test Api',
213+
'version': '0.0.1',
214+
},
215+
'paths': {
216+
'/test/{param1}': {
217+
'get': {
218+
'responses': {},
219+
},
220+
'parameters': [
221+
{
222+
'name': 'param1',
223+
'in': 'path',
224+
'schema': {
225+
'type': 'integer',
226+
'default': 'invaldtype',
227+
},
228+
},
229+
],
230+
},
231+
},
232+
}
233+
234+
errors = validator.iter_errors(spec)
235+
236+
errors_list = list(errors)
237+
assert len(errors_list) == 1
238+
assert errors_list[0].__class__ == ValidationError
239+
assert errors_list[0].message == (
240+
"'invaldtype' is not of type 'integer'"
241+
)

0 commit comments

Comments
 (0)