Esempio n. 1
0
    def __init__(self, schema=DEFAULT_LTM_SCHEMA):
        """Choose schema and initialize extended Draft4Validator.

        Raises:
            F5CcclSchemaError: Failed to read or validate the CCCL
            API schema file.
        """

        try:
            self.schema = read_yaml_or_json(schema)
        except json.JSONDecodeError as error:
            LOGGER.error("%s", error)
            raise cccl_exc.F5CcclSchemaError(
                'CCCL API schema could not be decoded.')
        except IOError as error:
            LOGGER.error("%s", error)
            raise cccl_exc.F5CcclSchemaError(
                'CCCL API schema could not be read.')

        try:
            Draft4Validator.check_schema(self.schema)
            self.validate_properties = Draft4Validator.VALIDATORS["properties"]
            validator_with_defaults = validators.extend(
                Draft4Validator,
                {"properties": self.__set_defaults})
            self.validator = validator_with_defaults(self.schema)
        except jsonschema.SchemaError as error:
            LOGGER.error("%s", error)
            raise cccl_exc.F5CcclSchemaError("Invalid API schema")
Esempio n. 2
0
def unique_by_key(validator_class):
    '''
    Factory function for validator with 'uniqueKey' check for objects array.
    '''
    validate_items = validator_class.VALIDATORS["items"]

    def unique_keys(validator, items, instance, schema):
        '''
        Checks for duplicate objects in array.
        '''
        for err in validate_items(validator, items, instance, schema):
            yield err
        if 'uniqueKey' not in items:
            return

        uniq_key = items['uniqueKey']
        keys_set = set()
        if validator.is_type(uniq_key, 'array'):
            get = lambda d: tuple(d.get(k, None) for k in uniq_key)
        else:
            get = lambda d: d.get(uniq_key, None)
        for i in instance:
            val = get(i)
            if val in keys_set:
                yield ValidationError(
                    'Duplicate value `{}` for key `{}`.'
                    .format(val, uniq_key)
                )
            keys_set.add(val)

    return validators.extend(validator_class, {'items': unique_keys})
Esempio n. 3
0
def extends(validator_class, partial):
    """Extend `Draft4Validator` with some validators."""

    def custom(validator, _custom, instance, schema):
        """Support user customized validators."""
        message = _custom(instance)
        if message is not None:
            yield ValidationError(message)

    def required(validator, _required, instance, schema):
        """Disable required validating if in partial mode.

        In normal (non-partial) mode, validate and yield errors with
        additional `path` and `schema_path` for each required field.
        """
        if partial:
            return

        if not validator.is_type(instance, "object"):
            return
        for property in _required:
            if property not in instance:
                yield ValidationError(
                    '%r is a required property' % property,
                    path=(property,), schema_path=(property,)
                )

    return validators.extend(
        validator_class, {'custom': custom, 'required': required},
    )
Esempio n. 4
0
def extend_with_default(validator_class):
    '''
    Factory function for validator with 'default' values substitution.
    '''
    validate_props = validator_class.VALIDATORS["properties"]
    validate_required = validator_class.VALIDATORS["required"]
    validate_type = validator_class.VALIDATORS["type"]

    def set_default(validator, props, instance, schema):
        '''
        Substitutes default value in a validating object instance.
        '''
        required = schema.get("required", [])

        valid = True
        for err in validate_required(validator, required, instance, schema):
            valid = False
            yield err
        for err in validate_props(validator, props, instance, schema):
            valid = False
            yield err

        for prop, subschema in props.iteritems():
            if "default" in subschema:
                typ = subschema["type"]
                default = subschema["default"]
                for err in validate_type(validator, typ, default, None):
                    valid = False
                    yield err
                if valid:
                    instance.setdefault(prop, default)

    return validators.extend(validator_class, {"properties": set_default})
Esempio n. 5
0
def test_validator_map(json_validation_spec_dir, spec):
    def validate_type(validator, types, instance, schema):
        types = _utils.ensure_list(types)
        errors = Draft4RequestValidator.VALIDATORS['type'](validator, types, instance, schema)
        for e in errors:
            yield e

        if 'string' in types and 'minLength' not in schema:
            errors = Draft4RequestValidator.VALIDATORS['minLength'](validator, 1, instance, schema)
            for e in errors:
                yield e

    MinLengthRequestValidator = extend(Draft4RequestValidator, {'type': validate_type})

    class MyRequestBodyValidator(RequestBodyValidator):
        def __init__(self, *args, **kwargs):
            super(MyRequestBodyValidator, self).__init__(*args, validator=MinLengthRequestValidator, **kwargs)

    validator_map = {'body': MyRequestBodyValidator}

    app = App(__name__, specification_dir=json_validation_spec_dir)
    app.add_api(spec, validate_responses=True, validator_map=validator_map)
    app_client = app.app.test_client()

    res = app_client.post('/v1.0/minlength', data=json.dumps({'foo': 'bar'}), content_type='application/json') # type: flask.Response
    assert res.status_code == 200

    res = app_client.post('/v1.0/minlength', data=json.dumps({'foo': ''}), content_type='application/json') # type: flask.Response
    assert res.status_code == 400
Esempio n. 6
0
File: config.py Progetto: d-tk/spack
def extend_with_default(validator_class):
    """Add support for the 'default' attribute for properties and patternProperties.

       jsonschema does not handle this out of the box -- it only
       validates.  This allows us to set default values for configs
       where certain fields are `None` b/c they're deleted or
       commented out.

    """
    validate_properties = validator_class.VALIDATORS["properties"]
    validate_pattern_properties = validator_class.VALIDATORS["patternProperties"]

    def set_defaults(validator, properties, instance, schema):
        for property, subschema in properties.iteritems():
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])
        for err in validate_properties(validator, properties, instance, schema):
            yield err

    def set_pp_defaults(validator, properties, instance, schema):
        for property, subschema in properties.iteritems():
            if "default" in subschema:
                if isinstance(instance, dict):
                    for key, val in instance.iteritems():
                        if re.match(property, key) and val is None:
                            instance[key] = subschema["default"]

        for err in validate_pattern_properties(validator, properties, instance, schema):
            yield err

    return validators.extend(validator_class, {
        "properties" : set_defaults,
        "patternProperties" : set_pp_defaults
    })
Esempio n. 7
0
    def test_object_extensions_can_handle_custom_validators(self):
        schema = {
            "type": "object",
            "required": ["x"],
            "properties": {"x": {"type": "integer"}},
        }

        type_checker = Draft4Validator.TYPE_CHECKER.redefine(
            u"object", is_object_or_named_tuple,
        )

        CustomValidator = extend(
            Draft4Validator,
            type_checker=type_checker,
            validators={"required": required, "properties": properties},
        )

        validator = CustomValidator(schema)

        Point = namedtuple("Point", ["x", "y"])
        # Can now process required and properties
        validator.validate(Point(x=4, y=5))

        with self.assertRaises(ValidationError):
            validator.validate(Point(x="not an integer", y=5))
Esempio n. 8
0
    def test_extend(self):
        validators = dict(self.Validator.VALIDATORS)
        new = mock.Mock()

        Extended = extend(self.Validator, validators={"a new one": new})

        validators.update([("a new one", new)])
        self.assertEqual(Extended.VALIDATORS, validators)
        self.assertEqual(Extended.META_SCHEMA, self.Validator.META_SCHEMA)
        self.assertEqual(Extended.DEFAULT_TYPES, self.Validator.DEFAULT_TYPES)
def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        for error in validate_properties(
            validator, properties, instance, schema,
        ):
            yield error

        for property, subschema in six.iteritems(properties):
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

    def oneOf_discriminator(validator, oneOf, instance, schema):
        subschemas = enumerate(oneOf)
        all_errors = []

        if 'discriminator' in schema:
            discriminator = schema['discriminator']
            if discriminator in instance:
                subschema = first_or_default(lambda s: s['$ref'] == instance[discriminator], oneOf)
                if subschema:
                    for err in validator.descend(instance, subschema):
                        yield err

                return

        for index, subschema in subschemas:
            errs = list(validator.descend(instance, subschema, schema_path=index))
            if not errs:
                first_valid = subschema
                break
            all_errors.extend(errs)
        else:
            yield ValidationError(
                "%r is not valid under any of the given schemas" % (instance,),
                context=all_errors,
            )

        more_valid = [s for i, s in subschemas if validator.is_valid(instance, s)]
        if more_valid:
            more_valid.append(first_valid)
            reprs = ", ".join(repr(schema) for schema in more_valid)
            yield ValidationError(
                "%r is valid under each of %s" % (instance, reprs)
            )

    return validators.extend(
        validator_class, {
            "properties": set_defaults,
            "oneOf": oneOf_discriminator
        },
    )
Esempio n. 10
0
def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS['properties']

    def set_defaults(validator, properties, instance, schema):
        for property, sub_schema in properties.iteritems():
            if "default" in sub_schema:
                instance.setdefault(property, sub_schema['default'])

        for error in validate_properties(validator, properties, instance, schema):
            yield error

    return validators.extend(validator_class, {"properties": set_defaults})
Esempio n. 11
0
def fill_defaults(validator_class):
    validate_props = validator_class.VALIDATORS['properties']

    def set_defaults(validator, props, instance, schema):
        for prop, subschema in props.items():
            if isinstance(instance, dict) and 'default' in subschema:
                instance.setdefault(prop, subschema['default'])

        for error in validate_props(validator, props, instance, schema):
            yield error

    return validators.extend(validator_class, {'properties': set_defaults})
Esempio n. 12
0
def get_validator_type(swagger_spec):
    """Create a custom jsonschema validator for Swagger 2.0 specs.

    :rtype: Its complicated. See jsonschema.validators.create()
    """
    return validators.extend(
        Draft4Validator,
        {
            'required': functools.partial(required_validator, swagger_spec),
            'enum': enum_validator,
            'type': functools.partial(type_validator, swagger_spec),
        })
Esempio n. 13
0
def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        for error in validate_properties(validator, properties, instance, schema):
            yield error

        for property, subschema in six.iteritems(properties):
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

    return validators.extend(validator_class, {"properties": set_defaults})
Esempio n. 14
0
    def test_object_can_be_extended(self):
        schema = {'type': 'object'}

        Point = namedtuple('Point', ['x', 'y'])

        type_checker = Draft4Validator.TYPE_CHECKER.redefine(
            u"object", is_object_or_named_tuple
        )

        CustomValidator = extend(Draft4Validator, type_checker=type_checker)
        v = CustomValidator(schema)

        v.validate(Point(x=4, y=5))
Esempio n. 15
0
    def test_object_can_be_extended(self):
        schema = {"type": "object"}

        Point = namedtuple("Point", ["x", "y"])

        type_checker = Draft4Validator.TYPE_CHECKER.redefine(
            u"object", is_object_or_named_tuple,
        )

        CustomValidator = extend(Draft4Validator, type_checker=type_checker)
        validator = CustomValidator(schema)

        validator.validate(Point(x=4, y=5))
Esempio n. 16
0
    def test_object_extensions_require_custom_validators(self):
        schema = {"type": "object", "required": ["x"]}

        type_checker = Draft4Validator.TYPE_CHECKER.redefine(
            u"object", is_object_or_named_tuple,
        )

        CustomValidator = extend(Draft4Validator, type_checker=type_checker)
        validator = CustomValidator(schema)

        Point = namedtuple("Point", ["x", "y"])
        # Cannot handle required
        with self.assertRaises(ValidationError):
            validator.validate(Point(x=4, y=5))
Esempio n. 17
0
    def test_default_types_update_type_checker(self):
        Validator = validators.create(
            meta_schema=self.meta_schema,
            validators=self.validators,
            default_types={u"array": list}
        )

        self.assertEqual(set(Validator.DEFAULT_TYPES), {u"array"})
        Extended = validators.extend(
            Validator,
            type_checker=Validator.TYPE_CHECKER.remove(u"array")
        )

        self.assertEqual(set(Extended.DEFAULT_TYPES), {})
Esempio n. 18
0
    def test_simple_type_can_be_extended(self):
        schema = {'type': 'integer'}

        type_checker = Draft4Validator.TYPE_CHECKER.redefine(
            "integer", is_int_or_string_int
        )

        CustomValidator = extend(Draft4Validator, type_checker=type_checker)
        v = CustomValidator(schema)

        v.validate(4)
        v.validate('4')

        with self.assertRaises(ValidationError):
            v.validate(4.4)
Esempio n. 19
0
def extend_with_default(validator_class):
    """
    This code was adapted from the jsonschema FAQ:
    http://python-jsonschema.readthedocs.org/en/latest/faq/
    """
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults_and_validate(validator, properties, instance, schema):
        for property, subschema in properties.iteritems():
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

        for error in validate_properties(validator, properties, instance, schema):
            yield error

    return validators.extend(validator_class, {"properties" : set_defaults_and_validate})
Esempio n. 20
0
    def test_extend(self):
        original_validators = dict(self.Validator.VALIDATORS)
        new = mock.Mock()

        Extended = validators.extend(
            self.Validator,
            validators={u"a new one": new},
        )

        original_validators.update([(u"a new one", new)])
        self.assertEqual(Extended.VALIDATORS, original_validators)
        self.assertNotIn(u"a new one", self.Validator.VALIDATORS)

        self.assertEqual(Extended.META_SCHEMA, self.Validator.META_SCHEMA)
        self.assertEqual(Extended.DEFAULT_TYPES, self.Validator.DEFAULT_TYPES)
        self.assertEqual(Extended.TYPE_CHECKER, self.Validator.TYPE_CHECKER)
Esempio n. 21
0
def extend_with_default(validator_class: Any) -> Any:
    """Append defaults from schema to instance need to be validated.

    :param validator_class: Apply the change for given validator class.
    """
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator: Any, properties: dict, instance: dict, schema: dict) -> Iterator[ValidationError]:
        for prop, subschema in properties.items():
            if "default" in subschema:
                instance.setdefault(prop, subschema["default"])

        for error in validate_properties(validator, properties, instance, schema):
            yield error  # pragma: no cover

    return extend(validator_class, {"properties": set_defaults})
Esempio n. 22
0
def extend_with_default(validator_cls):
    """ Applies default field from jsonschema

    Copied, with modificatios, from python-jsonschema FAQ. See:
    https://python-jsonschema.readthedocs.io/en/latest/faq/#why-doesn-t-my-schema-that-has-a-default-property-actually-set-the-default-on-my-instance
    """
    validate_props = validator_cls.VALIDATORS['properties']
    def set_defaults(validator, properties, instance, schema):
        for prop, subschema in six.iteritems(properties):
            if 'default' in subschema:
                instance.setdefault(prop, subschema['default'])

        for error in validate_props(validator, properties, instance, schema):
            yield error

    return validators.extend(validator_cls, {'properties': set_defaults})
Esempio n. 23
0
 def _extend_with_default(self, validator_class):
     validate_properties = validator_class.VALIDATORS["properties"]
     def set_defaults(validator, properties, instance, schema):
         for property, subschema in properties.iteritems():
             if "default" in subschema:
                 instance.setdefault(property, subschema["default"])
         for error in validate_properties(
                 validator, properties, instance, schema):
             yield error
     extended_validators = validators.extend(
         validator_class, {"properties" : set_defaults},
     )
     VALIDATORS = extended_validators.VALIDATORS
     for _validator in self.skip_validators:
         if VALIDATORS.get(_validator):
             del(VALIDATORS[_validator])
     return extended_validators
def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        if schema.get('title',None)=='Yadage Stage':
            if 'dependencies' in instance and type(instance['dependencies'])==list:
                log.debug('dependencies provided as list, assume jsonpath_ready predicate')
                instance['dependencies'] = {
                    "dependency_type" : "jsonpath_ready",
                    "expressions": instance["dependencies"]
                    }

        if "Scheduler" in schema.get('title','') and instance['scheduler_type'] in ['singlestep-stage','multistep-stage']:
            if(type(instance['parameters'])==dict):
                asarray = []
                for k,v in instance['parameters'].items():
                    if type(v) == dict and any(k in v for k in ['steps','stages','step']):
                        v['expression_type'] = 'stage-output-selector'
                    asarray.append({'key':k,'value':v})

                instance['parameters'] = asarray


        errors_found = False
        for error in validate_properties(
            validator, properties, instance, schema,
        ):
            errors_found = True
            yield error

        if errors_found: return

        for prop, subschema in properties.items():
            if "default" in subschema and type(instance) == dict:
                # Note not clear why this is the case, appeared in py3.X
                # intermittently on Travis
                instance.setdefault(prop, subschema["default"])

    validator = validators.extend(
        validator_class, {"properties" : set_defaults},
    )
    def validate(self, *args, **kwargs):
        for error in self.iter_errors(*args, **kwargs):
            pass
    validator.validate = validate
    return validator
Esempio n. 25
0
def extend_with_default(validator_class):
    """Append defaults from schema to instance need to be validated.

    :param validator_class: Apply the change for given validator class.
    """
    validate_properties = validator_class.VALIDATORS['properties']

    def set_defaults(validator, properties, instance, schema):
        for prop, subschema in properties.items():
            if 'default' in subschema:
                instance.setdefault(prop, subschema['default'])

        for error in validate_properties(
            validator, properties, instance, schema,
        ):
            yield error  # pragma: no cover

    return extend(validator_class, {'properties': set_defaults})
Esempio n. 26
0
def get_body_validator(models):
    """Returns a validator for the request body, based on a
    :class:`jsonschema.validators.Draft4Validator`, with extra validations
    added for swaggers extensions to jsonschema.

    :param models: a mapping of reference to models
    :returns: a :class:`jsonschema.validators.Validator` which can validate
        the request body.
    """
    return validators.extend(
        Draft4Validator,
        {
            'paramType': ignore,
            'name': ignore,
            'type': build_swagger_type_validator(models),
            'required': required_validator,
        }
    )
Esempio n. 27
0
    def extend_with_default(self, validator_class):
        '''
        Method to add default fields to our schema validation
        ( From the docs )
        '''
        validate_properties = validator_class.VALIDATORS["properties"]

        def set_defaults(validator, properties, instance, schema):
            for error in validate_properties(
                    validator, properties, instance, schema,
            ):
                yield error

            for property, subschema in properties.iteritems():
                if "default" in subschema:
                    instance.setdefault(property, subschema["default"])

        return validators.extend(
            validator_class, {"properties": set_defaults},
        )
def create_dereffing_validator(instance_resolver):
    """Create a customized Draft4Validator that follows $refs in the schema
    being validated (the Swagger spec for a service). This is not to be
    confused with $refs that are in the schema that describes the Swagger 2.0
    specification.

    :param instance_resolver: resolver for the swagger service's spec
    :type instance_resolver: :class:`jsonschema.RefResolver`

    :rtype: Its complicated. See jsonschema.validators.create()
    """
    visited_refs = {}

    validators_to_bound = {
        '$ref',
        'additionalProperties',
        'allOf',
        'anyOf',
        'dependencies',
        'maxProperties',
        'minProperties',
        'not',
        'oneOf',
        'patternProperties',
        'properties',
        'required',
        'type',
    }

    bound_validators = {
        k: functools.partial(
            validator_wrapper,
            instance_resolver=instance_resolver,
            visited_refs=visited_refs,
            default_validator_callable=v,
        ) if k in validators_to_bound else v
        for k, v in iteritems(Draft4Validator.VALIDATORS)
    }

    return validators.extend(Draft4Validator, bound_validators)
def create_dereffing_validator(instance_resolver):
    """Create a customized Draft4Validator that follows $refs in the schema
    being validated (the Swagger spec for a service). This is not to be
    confused with $refs that are in the schema that describes the Swagger 2.0
    specification.

    :param instance_resolver: resolver for the swagger service's spec
    :type instance_resolver: :class:`jsonschema.RefResolver`

    :rtype: Its complicated. See jsonschema.validators.create()
    """
    visited_refs = {}

    custom_validators = {
        '$ref': _validators.ref,
        'properties': _validators.properties_draft4,
        'additionalProperties': _validators.additionalProperties,
        'patternProperties': _validators.patternProperties,
        'type': _validators.type_draft4,
        'dependencies': _validators.dependencies,
        'required': _validators.required_draft4,
        'minProperties': _validators.minProperties_draft4,
        'maxProperties': _validators.maxProperties_draft4,
        'allOf': _validators.allOf_draft4,
        'oneOf': _validators.oneOf_draft4,
        'anyOf': _validators.anyOf_draft4,
        'not': _validators.not_draft4,
    }

    bound_validators = {}
    for k, v in iteritems(custom_validators):
        bound_validators[k] = functools.partial(
            validator_wrapper,
            instance_resolver=instance_resolver,
            visited_refs=visited_refs,
            default_validator_callable=v)

    return validators.extend(Draft4Validator, bound_validators)
Esempio n. 30
0
    def _extend_config_with_default(validator_class):
        validate_properties = validator_class.VALIDATORS["properties"]

        def set_defaults(validator, properties, instance, schema):
            # Do it only for root.
            if instance != {}:
                return
            for property, subschema in properties.iteritems():
                main_dict = {}
                for property2, subschema2 in subschema["properties"].iteritems():
                    sub_dict = {}
                    for property3, subschema3 in subschema2["properties"].iteritems():
                        if "default" in subschema3:
                            sub_dict[property3] = subschema3["default"]
                    main_dict[property2] = sub_dict
                instance.setdefault(property, main_dict)

            for error in validate_properties(validator, properties, instance, schema):
                yield error

        return validators.extend(
            validator_class, {"properties": set_defaults},
        )
Esempio n. 31
0
        """Check is instance of type."""
        if is_env_variable(instance):
            return True
        return super().is_type(instance, type)


def ownAdditionalProperties(validator, aP, instance, schema):
    """Additioinal properties validator."""
    for _ in additionalProperties(validator, aP, instance, schema):
        raise ExtraPropertiesError(
            list(find_additional_properties(instance, schema)))
    return iter(())


OwnDraft4Validator = extend(
    validator=Draft4Validator,
    validators={"additionalProperties": ownAdditionalProperties},
)

EnvVarsFriendlyDraft4Validator = extend(
    validator=Draft4Validator,
    type_checker=CustomTypeChecker(Draft4Validator.TYPE_CHECKER._type_checkers  # pylint: disable=protected-access
                                   ),
)


class ConfigValidator:
    """Configuration validator implementation."""
    def __init__(self, schema_filename: str, env_vars_friendly: bool = False):
        """
        Initialize the parser for configuration files.
Esempio n. 32
0
    def set_defaults(validator, properties, instance, schema):
        for property_, subschema in six.iteritems(properties):
            if "default" in subschema:
                instance.setdefault(property_, subschema["default"])

        for error in validate_properties(validator, properties, instance,
                                         schema):
            yield error

    return extend(validator_class, {"properties": set_defaults})


Draft4RequestValidator = extend_with_set_default(
    extend(
        Draft4Validator, {
            'type': validate_type,
            'enum': validate_enum,
            'required': validate_required,
            'readOnly': validate_readOnly
        }))

Draft4ResponseValidator = extend_with_set_default(
    extend(
        Draft4Validator, {
            'type': validate_type,
            'enum': validate_enum,
            'required': validate_required,
            'writeOnly': validate_writeOnly,
            'x-writeOnly': validate_writeOnly
        }))
Esempio n. 33
0
try:
    import pandas
except ImportError:
    pass
else:

    def data_frame(description):
        return primitive("data_frame", description)

    def is_data_frame(_checker, value):
        return isinstance(value, pandas.DataFrame)

    _TYPE_CHECKER = _TYPE_CHECKER.redefine("data_frame", is_data_frame)


CustomValidator = extend(jsonschema.Draft7Validator, type_checker=_TYPE_CHECKER)


def validate(schema, value, cls=CustomValidator, **kwargs):
    cls(schema, format_checker=jsonschema.draft7_format_checker).validate(
        value, **kwargs
    )


schema = {"type": "data_frame"}

value = pandas.DataFrame({"x": [1]})


def test():
    try:
                    if 'x-writeOnly' in validator.VALIDATORS and subschema.get(
                            'x-writeOnly') is True:
                        continue
            yield ValidationError("%r is a required property" % prop)


def validate_readOnly(validator, ro, instance, schema):
    yield ValidationError("Property is read-only")


def validate_writeOnly(validator, wo, instance, schema):
    yield ValidationError("Property is write-only")


Draft4RequestValidator = extend(
    Draft4Validator, {
        'type': validate_type,
        'enum': validate_enum,
        'required': validate_required,
        'readOnly': validate_readOnly
    })

Draft4ResponseValidator = extend(
    Draft4Validator, {
        'type': validate_type,
        'enum': validate_enum,
        'required': validate_required,
        'writeOnly': validate_writeOnly,
        'x-writeOnly': validate_writeOnly
    })
    for prop, subschema in properties.items():
        if "default" in subschema:
            instance.setdefault(prop, subschema["default"])

    return Draft6Validator.VALIDATORS["properties"](validator, properties, instance, schema)


validator_overrides = {
    "anyOf": None,
    "properties": set_defaults,
    "required": None,
    "oneOf": None,
    "not": None,
}

DefaultValidator = validators.extend(Draft6Validator, validator_overrides)
RequiredValidator = Draft6Validator


class ActionModule(ActionBase):
    def run(self, tmp=None, task_vars=None):
        action_vars = self._task.args

        if 'instance' not in action_vars:
            raise AnsibleError("instance parameter missing")

        if 'schema' not in action_vars:
            raise AnsibleError("schema parameter missing")

        instance_copy = copy.deepcopy(action_vars['instance'])
        try:
Esempio n. 36
0
from functools import partial
from connexion.decorators import response as r
from connexion.decorators.validation import ResponseBodyValidator
from jsonschema.validators import Draft4Validator, extend
from jsonschema._validators import type_draft4


def type_custom(validator,
                types,
                instance,
                schema,
                nullable_attr="x-nullable"):
    if schema.get(nullable_attr, False):
        if not isinstance(types, (list, tuple)):
            types = [types]
        types.append("null")
    yield from type_draft4(validator, types, instance, schema)


CustomValidator = extend(Draft4Validator, {
    "type": type_custom,
})

# monkey patch
r.ResponseBodyValidator = partial(ResponseBodyValidator,
                                  validator=CustomValidator)
Esempio n. 37
0
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Record validators."""

from jsonschema.validators import Draft4Validator, extend

PartialDraft4Validator = extend(Draft4Validator, {'required': None})
"""Partial JSON Schema (draft 4) validator.

Special validator that contains the same validation rules of Draft4Validator,
except for required fields.
"""
    type_checker=oas_types.oas30_type_checker,
    # NOTE: version causes conflict with global jsonschema validator
    # See https://github.com/p1c2u/openapi-schema-validator/pull/12
    # version="oas30",
    id_of=lambda schema: schema.get(u"id", ""),
)

BaseOAS31Validator = extend(
    Draft202012Validator,
    {
        # adjusted to OAS
        u"allOf": oas_validators.allOf,
        u"oneOf": oas_validators.oneOf,
        u"anyOf": oas_validators.anyOf,
        u"description": oas_validators.not_implemented,
        u"format": oas_validators.format,
        # fixed OAS fields
        u"discriminator": oas_validators.not_implemented,
        u"xml": oas_validators.not_implemented,
        u"externalDocs": oas_validators.not_implemented,
        u"example": oas_validators.not_implemented,
    },
    type_checker=oas31_type_checker,
)


@attrs
class OAS30Validator(BaseOAS30Validator):

    read: bool = attrib(default=None)
    write: bool = attrib(default=None)
Esempio n. 39
0
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <*****@*****.**>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from jsonschema import validators

from designate.schema import _validators

Draft3Validator = validators.extend(validators.Draft3Validator,
                                    validators={
                                        "type": _validators.type_draft3,
                                        "oneOf": _validators.oneOf_draft3,
                                    })

Draft4Validator = validators.extend(validators.Draft4Validator,
                                    validators={
                                        "type": _validators.type_draft4,
                                    })
def _create_validator(schema, enforce_defaults: bool):
    cls = validator_for(schema)
    cls.check_schema(schema)
    if enforce_defaults:
        cls = extend(cls, {"default": _default_validator})
    return cls(schema)
Esempio n. 41
0
    if subject is not None:
        metadata["subject"] = subject

    file_information = {
        "filename": os.path.basename(filepath),
        "mimetype": mimetype,
        "metadata": metadata,
    }

    return file_information


# json schema validation

# use the type check from Draft4Validator, because Draft7 considers 1.0 as integer
CustomValidator = validators.extend(Draft7Validator,
                                    type_checker=Draft4Validator.TYPE_CHECKER)


def validate_against_schema(instance, schema, raise_exception=True):

    # load schema object
    schema = load_schema(schema, False)

    # get the absolute path and setup a resolver
    schema_abs_path = "file:///{0}/".format(
        os.path.abspath(schemas_folder()).replace("\\", "/"))
    resolver = RefResolver(schema_abs_path, schema)
    validator = CustomValidator(schema=schema, resolver=resolver)

    # validate against schema and catch eventual exception
    try:
def extend_with_default(validator_class=Draft7Validator):
    """
    Extends a validator class to add defaults before validation.
    From: https://github.com/Julian/jsonschema/blob/master/docs/faq.rst
    """
    validate_props = validator_class.VALIDATORS["properties"]
    validate_array = validator_class.VALIDATORS["items"]

    def set_defaults(validator, properties, instance, schema):
        """ Set defaults within a "properties" context """
        if not validator.is_type(instance, "object"):
            return
        for prop, subschema in properties.items():
            if instance.get(prop) is None:
                if "default" in subschema:
                    default_val = subschema["default"]
                elif subschema.get("type") == "array":
                    default_val = []
                elif subschema.get("type") == "object":
                    default_val = {}
                else:
                    continue
                instance[prop] = default_val

        for error in validate_props(validator, properties, instance, schema):
            yield error

    def set_array_defaults(validator, properties, instance, schema):
        """ Set defaults within an "array" context """
        if not validator.is_type(instance, "array"):
            return

        if not instance:
            default_val = None
            if "default" in properties:
                default_val = properties["default"]
            elif properties.get("type") == "array":
                default_val = []
            elif properties.get("type") == "object":
                default_val = {}
            if default_val is not None:
                instance.append(default_val)
        for error in validate_array(validator, properties, instance, schema):
            yield error

    def set_oneOf_defaults(validator, properties, instance, schema):
        """ 
        Set defaults within a "oneOf" context. This ensures that only
        defaults from the matching subschema are set on the instance.

        TODO: If we ever use other optional subschema contexts (ex: allOf, anyOf)
              then we should implement custom validator functions for those as 
              well.
        """

        good_properties = []
        all_errors = []
        good_instance = None

        for i, subschema in enumerate(properties):
            new_instance = deepcopy(instance)
            # first time to fill in defaults since validating 'required', 'minProperties',
            # etc. can't be done until the instance has been properly filled with defaults.
            list(validator.descend(new_instance, subschema, schema_path=i))
            errs = list(
                validator.descend(new_instance, subschema, schema_path=i))
            if errs:
                all_errors.extend(errs)
            else:
                good_properties.append(subschema)
                good_instance = new_instance

        if len(good_properties) == 0:
            msg = f"{instance} is not valid under any of the given schemas"
            yield ValidationError(msg, context=all_errors)
        elif len(good_properties) > 1:
            msg = f'{instance} is valid under each of {", ".join(repr(p) for p in good_properties)}'
            yield ValidationError(msg)
        else:
            instance.clear()
            instance.update(good_instance)

    custom_validators = {
        "properties": set_defaults,
        "items": set_array_defaults,
        "oneOf": set_oneOf_defaults,
    }

    return validators.extend(validator_class, custom_validators)
Esempio n. 43
0
def emit_defaults(schema,
                  include_yaml_comments=False,
                  yaml_indent=2,
                  base_cls=None,
                  *args,
                  **kwargs):
    """
    Emit all default values for the given schema.
    
    Similar to calling ``validate({}, schema, inject_defaults=True)``, except:
    
    1. Ignore schema validation errors and 'required' property errors
    
    2. If no default is given for a property, inject ``"{{NO_DEFAULT}}"``,
       even if the property isn't supposed to be a string.
       
    3. If ``include_yaml_comments`` is True, insert ``CommentedMap`` objects instead of ordinary dicts,
       and insert a comment above each key, with the contents of the property ``"description"`` in the schema.
    
    Args:
        schema:
            The schema data to pull defaults from

        include_yaml_comments:
            Whether or not to return ``ruamel.yaml`` objects so that
            comments will be written when the data is dumped to YAML.
    
        yaml_indent:
            To ensure correctly indented comments, you must specify the indent
            step you plan to use when this data is eventually dumped as yaml.
    
    Returns:
        A copy of instance, with default values injected, and comments if specified.
    """
    instance = {}

    if include_yaml_comments:
        instance = CommentedMap(instance)
        instance.key_indent = 0  # monkey-patch!
        if "description" in schema:
            instance.yaml_set_start_comment('\n' + schema["description"] +
                                            '\n\n')
    else:
        instance = dict(instance)

    if base_cls is None:
        base_cls = validators.validator_for(schema)
    base_cls.check_schema(schema)

    def is_object(checker, instance):
        return (base_cls.TYPE_CHECKER.is_type(instance, "object")
                or isinstance(instance, (ordereddict, CommentedMap)))

    def is_array(checker, instance):
        return (base_cls.TYPE_CHECKER.is_type(instance, "array")
                or isinstance(instance, CommentedSeq))

    # By default, jsonschema expects JSON objects to be of type 'dict'.
    # We also want to permit ruamel.yaml.comments.CommentedSeq and CommentedMap
    type_checker = base_cls.TYPE_CHECKER.redefine_many({
        "object": is_object,
        "array": is_array
    })

    cls = validators.extend(base_cls, type_checker=type_checker)

    # Add default-injection behavior to the validator
    cls = extend_with_default_without_validation(cls, include_yaml_comments,
                                                 yaml_indent)
    extended_validator = cls(schema, *args, **kwargs)

    # Inject defaults.
    extended_validator.validate(instance)
    return instance
Esempio n. 44
0
import json
from jsonschema import Draft7Validator, TypeChecker, FormatChecker
from jsonschema.validators import extend
from application.utils.datetime_utils import str_to_datetime, is_interval, is_datetime
from application.collections_db import Couriers, Orders
from flask import Response

# Create validator extended with custom types 'interval' and 'datetime'
type_checker = Draft7Validator.TYPE_CHECKER \
    .redefine("interval", is_interval) \
    .redefine("datetime", is_datetime)
ValidatorWithDatetime = extend(Draft7Validator, type_checker=type_checker)

# Response for not application/json headers
bad_header = Response(json.dumps({'error': 'Content-Type must be application/json'}), 400,
                      headers={'Content-Type': 'application/json'})


def validate_couriers(couriers_data: dict) -> (dict, int):
    with open('application/schemas/CouriersPostRequest.json') as f:
        couriers_post_schema = ValidatorWithDatetime(json.load(f))
    return _validate_post_items(couriers_data, couriers_post_schema, 'courier')


def validate_orders(orders_data: dict) -> (dict, int):
    with open('application/schemas/OrdersPostRequest.json') as f:
        orders_post_schema = ValidatorWithDatetime(json.load(f))
    return _validate_post_items(orders_data, orders_post_schema, 'order')


def validate_update_courier(new_data: dict, courier_id, couriers_db: Couriers) -> (dict, int):
Esempio n. 45
0
"""
This module contains the `OpenAPISchemaValidator`.

The `OpenAPISchemaValidator` extends the `jsonschema.Draft4Validator`
with the functionalities as described in :swagger:`schemaObject`.

"""
from jsonschema import Draft4Validator
from jsonschema.validators import extend

#: This extended validator implements the extra formats specified by the
#: Open API specification.
OpenAPISchemaValidator = extend(Draft4Validator, {})
def get_s4s_validator(fetcher):
    type_checker = TYPE_CHECKER.redefine('reference',
                                         make_reference_type(fetcher))
    return extend(Draft6Validator,
                  validators=VALIDATORS,
                  type_checker=type_checker)
Esempio n. 47
0
# -*- coding: utf-8 -*-
#
# This file is part of CERN Analysis Preservation Framework.
# Copyright (C) 2016 CERN.
#
# CERN Analysis Preservation Framework is free software; you can redistribute
# it and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# CERN Analysis Preservation Framework is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CERN Analysis Preservation Framework; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, CERN does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.
"""Record validators."""

from jsonschema import Draft4Validator
from jsonschema.validators import extend

record_validators = dict(Draft4Validator.VALIDATORS)
RecordValidator = extend(Draft4Validator, validators=record_validators)
Esempio n. 48
0
try:
    from jsonschema import Draft7Validator
    from jsonschema.validators import extend
except ImportError:
    raise ImportError(
        'Cannot find "jsonschema" package. Either install it manually '
        'with pip, or install confj with validation option: '
        'pip install confj[validation]')

from .confdata import ConfigData


# pylint: disable=W0613
def is_config(checker, instance):
    return (Draft7Validator.TYPE_CHECKER.is_type(instance, "object")
            or isinstance(instance, ConfigData))


TYPE_CHECKER = Draft7Validator.TYPE_CHECKER.redefine("object", is_config)

ConfigValidator = extend(Draft7Validator, type_checker=TYPE_CHECKER)
CONFIG_VALIDATOR = ConfigValidator(schema={"type": "object"})
Esempio n. 49
0
    def test_extending_a_legacy_validator_does_not_rewarn(self):
        Validator = validators.create(meta_schema={}, default_types={})
        self.assertTrue(self.flushWarnings())

        validators.extend(Validator)
        self.assertFalse(self.flushWarnings())
Esempio n. 50
0
    """
    return validators.extend(
        Draft4Validator,
        {
            'paramType': ignore,
            'name': ignore,
            'type': build_swagger_type_validator(models),
            'required': required_validator,
        }
    )


Swagger12ParamValidator = validators.extend(
    Draft3Validator,
    {
        'paramType': ignore,
        'name': ignore,
        'type': type_validator,
    }
)


class ValidatorMap(
    namedtuple('_VMap', 'query path form headers body response')
):
    """
    A data object with validators for each part of the request and response
    objects. Each field is a :class:`SchemaValidator`.
    """
    __slots__ = ()

    @classmethod
Esempio n. 51
0
def extend_with_no_checks_for_required(validator_class):
    def no_checks(_validator, _properties, _instance, _schema):
        return

    return extend(validator_class, {"required": no_checks})
Esempio n. 52
0
@fixture
def json_schema_merge(request):
    schema_path = os.path.join(schema_dir, 'merge_format.schema.json')
    with io.open(schema_path, encoding="utf8") as f:
        schema_json = json.load(f)
    return schema_json


def is_sequence(checker, instance):
    return isinstance(instance, Sequence)


type_checker = Validator.TYPE_CHECKER.redefine("array", is_sequence)

CustomValidator = extend(Validator, type_checker=type_checker)


@fixture
def merge_validator(request, json_schema_merge):
    return CustomValidator(
        json_schema_merge,
        resolver=RefResolver(
            'file://localhost/' + schema_dir.replace('\\', '/') + '/',
            json_schema_merge),
    )


@fixture(scope='session')
def ioloop_patch():
    from nbdime.webapp.nbdimeserver import asyncio_patch
Esempio n. 53
0
from ..exceptions import ValidationError


def _nullable(base_validator):
    def _validator(validator, v, instance, schema):
        if instance is None and schema.get('nullable'):
            return
        for error in base_validator(validator, v, instance, schema):
            yield error

    return _validator


_Validator = validators.extend(
    Draft4Validator,
    {
        'type': _nullable(Draft4Validator.VALIDATORS['type']),
        'enum': _nullable(Draft4Validator.VALIDATORS['enum']),
    },
)


class SchemaValidator(object):
    def __init__(self, schema, format_checker=None):
        self._validator = _Validator(schema, format_checker=format_checker)

    def validate(self, instance, schema):
        errors = list(self._validator.iter_errors(instance, schema))
        if errors:
            raise ValidationError(errors)
from openapi_spec_validator import validate_spec
from jsonschema import Draft4Validator, Draft7Validator, RefResolver
from jsonschema.validators import extend
from jsonschema.exceptions import ValidationError
import pytest
from unittest import TestCase
from yaml import safe_load

from utils.invalids import INVALID_SYSTEM_PROFILES
from utils.valids import VALID_SYSTEM_PROFILES

CustomDraft4Validator = extend(
    Draft4Validator, {"x-propertyNames": Draft7Validator.VALIDATORS.get("propertyNames")}
)

class SystemProfileTests(TestCase):
    def setUp(self):
        super().setUp()

        with open('schemas/system_profile/v1.yaml') as spec_yaml:
            self.specification = safe_load(spec_yaml)
            self.resolver = RefResolver.from_schema(self.specification)

    def test_system_profile_invalids(self):
        for system_profile in INVALID_SYSTEM_PROFILES:
            with self.subTest(system_profile=system_profile):
                with pytest.raises(ValidationError):
                    CustomDraft4Validator(self.specification["$defs"]["SystemProfile"], resolver=self.resolver).validate(system_profile)
    
    def test_system_profile_valids(self):
        for system_profile in VALID_SYSTEM_PROFILES:
#
# You should have received a copy of the GNU General Public License
# along with CERN Analysis Preservation Framework; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, CERN does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.
"""Deposit validators."""

import os

from jsonschema import Draft4Validator
from jsonschema.validators import extend

from cap.modules.experiments.validators import (validate_cadi_id,
                                                validate_cms_trigger,
                                                validate_das_path)

deposit_validators = dict(Draft4Validator.VALIDATORS)

if not os.environ.get("CAP_CMS_VALIDATION_DISABLE"):
    deposit_validators['x-validate-cms-trigger'] = validate_cms_trigger
    deposit_validators['x-validate-das-path'] = validate_das_path
# deposit_validators['x-validate-cadi-id'] = validate_cadi_id

DepositValidator = extend(Draft4Validator, validators=deposit_validators)

NoRequiredValidator = extend(DepositValidator, {'required': None})
Esempio n. 56
0
def extend_with_default(validator_class):
    """
    Helper function for validate(..., inject_defaults=True)
    
    This code was adapted from the jsonschema FAQ:
    http://python-jsonschema.readthedocs.org/en/latest/faq/
    
    Unlike extend_with_default_without_validation(), below,
    this function does not bother to convert the defaults to
    commented YAML types before injecting them.
    (The results of this function are not meant for pretty-printing.)
    """
    validate_properties = validator_class.VALIDATORS["properties"]
    validate_items = validator_class.VALIDATORS["items"]

    def _set_property_defaults(properties, instance):
        for property_name, subschema in properties.items():
            if "default" in subschema:
                default = copy.deepcopy(subschema["default"])
                if isinstance(default, dict):
                    default = _Dict(default)
                    default.from_default = True
                instance.setdefault(property_name, default)

    def set_defaults_and_validate(validator, properties, instance, schema):
        _set_property_defaults(properties, instance)
        for error in validate_properties(validator, properties, instance,
                                         schema):
            yield error

    def fill_in_default_array_items(validator, items_schema, instance, schema):
        if "default" in items_schema and isinstance(items_schema["default"],
                                                    Mapping):
            new_items = []
            for item in instance:
                if not isinstance(item, Mapping):
                    new_items.append(item)
                else:
                    default = copy.deepcopy(items_schema["default"])
                    default = _Dict(default)
                    if item == {}:
                        # FIXME: Instead of a simple bool, it would be better to specify
                        #        WHICH properties in this dict were copied from the default value.
                        default.from_default = True
                    default.update(item)
                    new_items.append(default)

            instance.clear()
            instance.extend(new_items)

        # Descend into array list
        for error in validate_items(validator, items_schema, instance, schema):
            yield error

    def check_required(validator, required, instance, schema):
        # We only check 'required' properties that don't have specified defaults
        for prop in required:
            if prop in instance:
                continue
            if prop not in schema['properties'] or 'default' not in schema[
                    'properties'][prop]:
                yield ValidationError(
                    "%r is a required property and has no default value in your schema"
                    % prop)

    return validators.extend(
        validator_class, {
            "properties": set_defaults_and_validate,
            "items": fill_in_default_array_items,
            "required": check_required
        })
Esempio n. 57
0
        else:
            local_base_uri = local_base_uri[5:]

        try:
            local_filepath = os.path.abspath(os.path.join(local_base_uri, '../'+ref))
            local_schema = load_schema(local_filepath)
            schema_id = local_schema.get('$id', '')
            if schema_id:
                validator.resolver.store[schema_id] = local_schema
        except FileNotFoundError:
            pass

    return Draft7Validator.VALIDATORS['$ref'](validator, ref, instance, schema)


STIXValidator = extend(Draft7Validator, {'$ref': ref_store})


def load_validator(schema_path, schema):
    """Create a JSON schema validator for the given schema.

    Args:
        schema_path: The filename of the JSON schema.
        schema: A Python object representation of the same schema.

    Returns:
        An instance of Draft7Validator.

    """
    global SCHEMA_STORE
Esempio n. 58
0
                                      max_deviation):
            yield error


validators = {
    'required': _required,
    'x-required': _required,
    'file': _file,
    'x-file': _file,
    'fkey': _fkey,
    'x-fkey': _fkey,
    'unique': _unique,
    'x-unique': _unique,
    'unique-together': _unique,
    'x-unique-together': _unique,
    'x-check-geolocation': _check_geolocation,
}

_CustomDraft4Validator = extend(Draft4Validator, validators, str('draft4'))


class CustomDraft4Validator(_CustomDraft4Validator):
    def __init__(self, *args, **kwargs):
        self.datastore = kwargs.pop('datastore')
        self.upload_path = kwargs.pop('upload_path')

        self.index = kwargs.pop('index', None)
        self.doc_type = kwargs.pop('doc_type', None)

        super(CustomDraft4Validator, self).__init__(*args, **kwargs)
def get_json(path):
    with open(path) as f:
        return json.load(f)


def recommended_draft4(validator, required, instance, schema):
    if not validator.is_type(instance, "object"):
        return
    for prop in required:
        if prop not in instance:
            yield ValidationError("%r is a recommended property" % prop)

Draft4ValidatorExtended = extend(
    validator=Draft4Validator,
    validators={u"recommended": recommended_draft4},
    version="draft4e"
)


def is_integer(text):
    try:
        int(text)
        return True
    except ValueError:
        return False


def validate_item(item):
    file_name = SCHEMA_PATH + item['type'].rsplit('/', 1)[1]
    schema = get_json(file_name + '.json')
Esempio n. 60
0
def extend_with_default_without_validation(validator_class,
                                           include_yaml_comments=False,
                                           yaml_indent=2):
    validate_properties = validator_class.VALIDATORS["properties"]
    validate_items = validator_class.VALIDATORS["items"]

    def set_default_object_properties(validator, properties, instance, schema):
        for property, subschema in properties.items():
            if instance == "{{NO_DEFAULT}}":
                continue
            if "default" in subschema:
                default = copy.deepcopy(subschema["default"])

                if isinstance(default, list):
                    try:
                        # Lists of numbers should use 'flow style'
                        # and so should lists-of-lists of numbers
                        # (e.g. bounding boxes like [[0,0,0],[1,2,3]])
                        if (subschema["items"]["type"] in ("integer", "number")
                                or (subschema["items"]["type"] == "array"
                                    and subschema["items"]["items"]["type"]
                                    in ("integer", "number"))):
                            default = flow_style(default)
                    except KeyError:
                        pass

                if include_yaml_comments and isinstance(default, dict):
                    default = CommentedMap(default)
                    # To keep track of the current indentation level,
                    # we just monkey-patch this member onto the dict.
                    default.key_indent = instance.key_indent + yaml_indent
                    default.from_default = True
                if include_yaml_comments and isinstance(default, list):
                    if not isinstance(default, CommentedSeq):
                        default = CommentedSeq(copy.copy(default))

                    # To keep track of the current indentation level,
                    # we just monkey-patch this member onto the dict.
                    default.key_indent = instance.key_indent + yaml_indent
                    default.from_default = True
                if property not in instance:
                    instance[property] = default
            else:
                if property not in instance:
                    instance[property] = "{{NO_DEFAULT}}"

            if include_yaml_comments and "description" in subschema:
                comment = '\n' + subschema["description"]
                if comment[-1] == '\n':
                    comment = comment[:-1]
                instance.yaml_set_comment_before_after_key(
                    property, comment, instance.key_indent)

        for _error in validate_properties(validator, properties, instance,
                                          schema):
            # Ignore validation errors
            pass

    def fill_in_default_array_items(validator, items, instance, schema):
        if include_yaml_comments and items["type"] == "object":
            new_items = []
            for item in instance:
                new_item = CommentedMap(item)
                new_item.key_indent = instance.key_indent + yaml_indent
                new_items.append(new_item)
            instance.clear()
            instance.extend(new_items)

        # Descend into array list
        for _error in validate_items(validator, items, instance, schema):
            # Ignore validation errors
            pass

    def ignore_required(validator, required, instance, schema):
        return

    return validators.extend(
        validator_class, {
            "properties": set_default_object_properties,
            "items": fill_in_default_array_items,
            "required": ignore_required
        })