Skip to content

Commit

Permalink
Create validate_defaults function by passing in the instance_validator
Browse files Browse the repository at this point in the history
The instance_validator was previously set as an attribute on the
OpenApiValidator. However with the jsonschema upgrade to 4.0.0, this
attribute is no longer maintained while descending into the spec.
Presumably because jsonschema now relies on attrs.resolve.
  • Loading branch information
RobbeSneyders committed Jan 22, 2022
1 parent 859078b commit 207f9ff
Showing 1 changed file with 30 additions and 23 deletions.
53 changes: 30 additions & 23 deletions connexion/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import copy
import json
import pathlib
import typing as t
from collections.abc import Mapping
from urllib.parse import urlsplit

Expand All @@ -24,33 +25,37 @@
validate_properties = Draft4Validator.VALIDATORS["properties"]


def validate_defaults(validator, properties, instance, schema):
"""Validate `properties` subschema.
def create_validate_default_fn(instance_validator: Draft4Validator) -> t.Callable:
"""Creates a validation function for property defaults. This validation function will be used
by a validator that validates an openapi spec against the openapi schema. The default value
however needs to be validated against the openapi spec itself.
:param instance_validator: A validator to validate defaults against the openapi spec itself
instead of against the openapi schema.
:return: A validation function for property defaults using the passed in instance_validator
Enforcing each default value validates against the schema in which it resides.
"""
valid = True
for error in validate_properties(
validator, properties, instance, schema,
):
valid = False
yield error

# Validate default only when the subschema has validated successfully
# and only when an instance validator is available.
if not valid or not hasattr(validator, 'instance_validator'):
return
if isinstance(instance, dict) and 'default' in instance:
for error in validator.instance_validator.iter_errors(
instance['default'],
instance
):

def validate_defaults(validator, properties, instance, schema):
"""Validate `properties` subschema.
Enforcing each default value validates against the schema in which it resides.
"""
valid = True
for error in validate_properties(validator, properties, instance, schema):
valid = False
yield error

# Validate default only when the subschema has validated successfully
if not valid:
return
if isinstance(instance, dict) and 'default' in instance:
for error in instance_validator.iter_errors(instance['default'], instance):
yield error

return validate_defaults

OpenApiValidator = extend_validator(
Draft4Validator, {"properties": validate_defaults},
)

NO_SPEC_VERSION_ERR_MSG = """Unable to get the spec version.
You are missing either '"swagger": "2.0"' or '"openapi": "3.0.0"'
Expand Down Expand Up @@ -83,8 +88,10 @@ def _validate_spec(cls, spec):
""" validate spec against schema
"""
try:
instance_validator = Draft4Validator(spec)
validate_defaults = create_validate_default_fn(instance_validator)
OpenApiValidator = extend_validator(Draft4Validator, {"properties": validate_defaults})
validator = OpenApiValidator(cls.openapi_schema)
validator.instance_validator = Draft4Validator(spec)
validator.validate(spec)
except jsonschema.exceptions.ValidationError as e:
raise InvalidSpecification.create_from(e)
Expand Down

0 comments on commit 207f9ff

Please sign in to comment.