Skip to content

Commit 50caf1e

Browse files
authored
Merge pull request #154 from hibougeek/feat/#97_handle_required_in_allof
feat: handle allof when required linked to parent object (#97)
2 parents ce49ffe + 9c9213a commit 50caf1e

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

Diff for: openapi_spec_validator/validators.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -120,23 +120,33 @@ class SchemaValidator(object):
120120
def __init__(self, dereferencer):
121121
self.dereferencer = dereferencer
122122

123+
def _nested_properties(self, schema):
124+
schema_deref = self.dereferencer.dereference(schema)
125+
return schema_deref.get("properties", {}).keys()
126+
123127
@wraps_errors
124128
def iter_errors(self, schema, require_properties=True):
125129
schema_deref = self.dereferencer.dereference(schema)
126130
if not isinstance(schema_deref, dict):
127131
return
128132

133+
nested_properties = []
129134
if 'allOf' in schema_deref:
130135
for inner_schema in schema_deref['allOf']:
131136
for err in self.iter_errors(
132-
inner_schema,
133-
require_properties=False
137+
inner_schema,
138+
require_properties=False
134139
):
135140
yield err
141+
nested_properties = nested_properties + list(self._nested_properties(inner_schema))
136142

137143
required = schema_deref.get('required', [])
138144
properties = schema_deref.get('properties', {}).keys()
139-
extra_properties = list(set(required) - set(properties))
145+
if 'allOf' in schema_deref:
146+
extra_properties = list(set(required) - set(properties) - set(nested_properties))
147+
else:
148+
extra_properties = list(set(required) - set(properties))
149+
140150
if extra_properties and require_properties:
141151
yield ExtraParametersError(
142152
"Required list has not defined properties: {0}".format(

Diff for: tests/integration/test_validators.py

+46
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,52 @@ def test_allow_allof_required_no_properties(self, validator_v30):
162162
errors_list = list(errors)
163163
assert errors_list == []
164164

165+
def test_allow_allof_when_required_is_linked_to_the_parent_object(self, validator_v30):
166+
spec = {
167+
'openapi': '3.0.1',
168+
'info': {
169+
'title': 'Test Api',
170+
'version': '0.0.1',
171+
},
172+
'paths': {},
173+
'components': {
174+
'schemas': {
175+
'Address': {
176+
'type': 'object',
177+
'properties': {
178+
'SubdivisionCode': {
179+
'type': 'string',
180+
'description': 'State or region'
181+
},
182+
'Town': {
183+
'type': 'string',
184+
'description': 'Town or city'
185+
},
186+
'CountryCode': {
187+
'type': 'string',
188+
}
189+
}
190+
},
191+
'AddressCreation': {
192+
'required': [
193+
'CountryCode',
194+
'Town'
195+
],
196+
'type': 'object',
197+
'allOf': [
198+
{
199+
'$ref': '#/components/schemas/Address'
200+
}
201+
]
202+
}
203+
}
204+
}
205+
}
206+
207+
errors = validator_v30.iter_errors(spec)
208+
errors_list = list(errors)
209+
assert errors_list == []
210+
165211
def test_extra_parameters_in_required(self, validator_v30):
166212
spec = {
167213
'openapi': '3.0.0',

0 commit comments

Comments
 (0)