diff --git a/openapi_spec_validator/validators.py b/openapi_spec_validator/validators.py index 58ffc7f..862ccec 100644 --- a/openapi_spec_validator/validators.py +++ b/openapi_spec_validator/validators.py @@ -120,23 +120,33 @@ class SchemaValidator(object): def __init__(self, dereferencer): self.dereferencer = dereferencer + def _nested_properties(self, schema): + schema_deref = self.dereferencer.dereference(schema) + return schema_deref.get("properties", {}).keys() + @wraps_errors def iter_errors(self, schema, require_properties=True): schema_deref = self.dereferencer.dereference(schema) if not isinstance(schema_deref, dict): return + nested_properties = [] if 'allOf' in schema_deref: for inner_schema in schema_deref['allOf']: for err in self.iter_errors( - inner_schema, - require_properties=False + inner_schema, + require_properties=False ): yield err + nested_properties = nested_properties + list(self._nested_properties(inner_schema)) required = schema_deref.get('required', []) properties = schema_deref.get('properties', {}).keys() - extra_properties = list(set(required) - set(properties)) + if 'allOf' in schema_deref: + extra_properties = list(set(required) - set(properties) - set(nested_properties)) + else: + extra_properties = list(set(required) - set(properties)) + if extra_properties and require_properties: yield ExtraParametersError( "Required list has not defined properties: {0}".format( diff --git a/tests/integration/test_validators.py b/tests/integration/test_validators.py index 46e9716..03d3ef2 100644 --- a/tests/integration/test_validators.py +++ b/tests/integration/test_validators.py @@ -162,6 +162,52 @@ def test_allow_allof_required_no_properties(self, validator_v30): errors_list = list(errors) assert errors_list == [] + def test_allow_allof_when_required_is_linked_to_the_parent_object(self, validator_v30): + spec = { + 'openapi': '3.0.1', + 'info': { + 'title': 'Test Api', + 'version': '0.0.1', + }, + 'paths': {}, + 'components': { + 'schemas': { + 'Address': { + 'type': 'object', + 'properties': { + 'SubdivisionCode': { + 'type': 'string', + 'description': 'State or region' + }, + 'Town': { + 'type': 'string', + 'description': 'Town or city' + }, + 'CountryCode': { + 'type': 'string', + } + } + }, + 'AddressCreation': { + 'required': [ + 'CountryCode', + 'Town' + ], + 'type': 'object', + 'allOf': [ + { + '$ref': '#/components/schemas/Address' + } + ] + } + } + } + } + + errors = validator_v30.iter_errors(spec) + errors_list = list(errors) + assert errors_list == [] + def test_extra_parameters_in_required(self, validator_v30): spec = { 'openapi': '3.0.0',
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: