Example #1
0
def oneOf(validator, oneOf, instance, schema, errors):
    valids = []
    all_errors = []
    for index, subschema in enumerate(oneOf):
        erroff = len(errors)
        ret = validator._descend(
            instance, subschema, errors, schema_path=index)
        if len(errors) == erroff:
            valids.append((ret, subschema))
        else:
            all_errors.extend(errors[erroff:])
            del errors[erroff:]

    if len(valids) == 1:
        return valids[0][0][0], oneOf

    if not valids:
        errors.append(ValidationError(
            '{} is not valid under any of the given schemas'.format(instance),
            context=all_errors,
        ))
    elif len(valids) > 1:
        errors.append(ValidationError(
            '{} is valid under each of {}'.format(
                instance, ', '.join(repr(schema) for _, schema in valids))))
Example #2
0
def additionalProperties(validator, aP, instance, schema, errors):
    if not validator.is_type(instance, 'object', schema):
        return

    extras = set()
    properties = schema.get("properties", {})
    patterns = schema.get("patternProperties", {})
    if patterns and isinstance(patterns, dict):
        patterns = validator._get_regex('|'.join(patterns))
    else:
        patterns = None
    for name in instance:
        if name not in properties:
            if patterns and patterns.search(name):
                continue
            extras.add(name)

    if validator.is_type(aP, 'object', schema):
        new_instance = dict(instance)
        for extra in extras:
            new_instance[extra], _ = validator._descend(
                instance[extra], aP, errors, path=extra)
        return new_instance, aP
    elif not aP and extras:
        if patterns:
            patterns = sorted(schema['patternProperties'])
            errors.append(ValidationError(
                '{} do not match any of the regexes: {}'.format(
                    ', '.join(map(repr, sorted(extras))),
                    ', '.join(map(repr, patterns)))))
        else:
            errors.append(ValidationError(
                'Additional properties are not allowed '
                '({} were unexpected)'.format(extras)))
Example #3
0
def required(validator, required, instance, schema, errors):
    if not validator.is_type(instance, 'object', schema):
        return
    for property in required:
        if property not in instance:
            errors.append(ValidationError(
                '{} is a required property'.format(property)))
Example #4
0
def not_(validator, not_, instance, schema, errors):
    tmp_errors = []
    validator._descend(instance, not_, tmp_errors)
    if len(tmp_errors) != 0:
        return
    errors.append(ValidationError(
        '{} is not allowed for {}'.format(not_, instance)))
Example #5
0
def format(validator, format, instance, schema, errors):
    if validator.format_checker is not None:
        try:
            instance = validator.format_checker.check(instance, format)
        except Exception as e:
            errors.append(ValidationError(str(e), cause=e.__cause__))
    return instance, format
Example #6
0
def multipleOf(validator, mO, instance, schema, errors):
    if not validator.is_type(instance, 'number', schema):
        return
    if isinstance(mO, float):
        quotient = instance / mO
        failed = int(quotient) != quotient
    else:
        failed = instance % mO
    if failed:
        errors.append(ValidationError(
            '{} is not a multiple of {}'.format(instance, mO)))
Example #7
0
def minimum(validator, minimum, instance, schema, errors):
    if not validator.is_type(instance, 'number', schema):
        return

    if schema.get('exclusiveMinimum', False):
        failed = instance <= minimum
        cmp = 'less than or equal to'
    else:
        failed = instance < minimum
        cmp = 'less than'
    if failed:
        errors.append(ValidationError(
            '{} is {} the minimum of {}'.format(instance, cmp, minimum)))
Example #8
0
def _validate_and_parse(Validator, resolver, request, path_matches, op_obj,
                        fill_by_default):
    params, queries = {}, {}
    if request.query_string:
        try:
            queries = parse_qs(request.query_string,
                               keep_blank_values=True,
                               strict_parsing=True)
        except Exception:
            raise HTTPBadRequest('cannot parse query string')
    for param_obj in op_obj.get('parameters', []):
        params.update(
            _validate_and_parse_param(Validator, request, param_obj,
                                      path_matches, queries, fill_by_default))

    body = None
    reqbody = op_obj.get('requestBody')
    if reqbody:
        if '$ref' in reqbody:
            _, reqbody = resolver.resolve(reqbody['$ref'])
        required = reqbody.get('required', False)
        body = request.body
        if required and not body:
            raise ValidationErrors(ValidationError('body is required'))
        accept_types = set(reqbody.get('content', {}).keys())
        if (body and
                not _validate_media_types(request.content_type, accept_types)):
            raise HTTPNotAcceptable
        media_type_obj = reqbody.get('content', {}).get(MIME_JSON)
        if media_type_obj is not None and body:
            try:
                body = json.loads(body.decode('utf8'))
            except Exception:
                raise ValidationErrors(ValidationError('invalid json'))
            json_schema = media_type_obj.get('schema')
            if json_schema:
                body = _validate(Validator, json_schema, body)
    return params, body
Example #9
0
def additionalItems(validator, aI, instance, schema, errors):
    if (not validator.is_type(instance, 'array', schema) or
            validator.is_type(schema.get('items', {}), 'object', schema)):
        return

    items_array = schema.get('items', [])
    if validator.is_type(aI, 'object', schema):
        new_instance = list(instance)
        for index, item in enumerate(
                instance[len(items_array):], start=len(items_array)):
            new_instance[index] = validator._descend(
                item, aI, errors, path=index)
    elif not aI and len(instance) > len(items_array):
        errors.append(ValidationError(
            'Additional items are not allowed ({} were unexpected)'.format(
                ', '.join([
                    str(x) for x in instance[len(items_array):]]))))
Example #10
0
    def validator_tween(request):
        route_info = route_mapper(request)
        route = route_info.get('route', None)
        if not route:  # pragma: no cover
            return handler(request)
        op_obj = get_operation_object(route.path, request.method)
        if not op_obj:  # pragma: no cover
            return handler(request)

        _check_security(default_security, request, op_obj)
        params, body = _validate_and_parse(Validator, resolver, request,
                                           route_info.get('match', {}), op_obj,
                                           fill_default)

        def oas3_data(_):
            return params

        def oas3_body(_):
            return body

        request.set_property(oas3_data)
        request.set_property(oas3_body)
        response = handler(request)
        if not validate_response:
            return response

        try:
            responses_obj = op_obj['responses']
            res_obj = responses_obj.get(str(response.status_code),
                                        responses_obj.get('default'))
            if res_obj is None:
                raise ValidationErrors(
                    ValidationError('invalid response status code'))
            content_prop = res_obj.get('content')
            if response.content_type == MIME_JSON:
                res_schema = content_prop.get(MIME_JSON, {}).get('schema')
                if res_schema:
                    res_json = json.loads(response.body.decode('utf8'))
                    if response_reviver:
                        res_json = apply_reviver(res_json, response_reviver)
                    _validate(Validator, res_schema, res_json)
        except Exception as e:
            raise ResponseValidationError(response, e)
        return response
Example #11
0
def anyOf(validator, anyOf, instance, schema, errors):
    valids, all_errors = [], []
    for index, subschema in enumerate(anyOf):
        erroff = len(errors)
        ret, _ = validator._descend(
            instance, subschema, errors, schema_path=index)
        if len(errors) == erroff:
            valids.append(ret)
        else:
            all_errors.extend(errors[erroff:])
            del errors[erroff:]

    if len(valids) > 0:
        return _utils.merge_instances(valids), anyOf

    errors.append(ValidationError(
        '{} is not valid under any of the given schemas'.format(instance),
        context=all_errors,
    ))
Example #12
0
def maxLength(validator, mL, instance, schema, errors):
    if (validator.is_type(instance, 'string', schema)
            and len(instance) > mL):
        errors.append(ValidationError('{} is too long'.format(instance,)))
Example #13
0
def pattern(validator, pattern, instance, schema, errors):
    if (validator.is_type(instance, 'string', schema) and
            not validator._get_regex(pattern).search(instance)):
        errors.append(ValidationError(
            '{} does not match {}'.format(instance, pattern)))
Example #14
0
def type(validator, types, instance, schema, errors):
    types = _utils.ensure_list(types)
    if not any(validator.is_type(instance, type, schema) for type in types):
        errors.append(ValidationError('{} is not of type {}'.format(
            instance, ', '.join(types))))
Example #15
0
def uniqueItems(validator, uI, instance, schema, errors):
    if (uI and validator.is_type(instance, 'array', schema) and
            not _utils.is_uniq(instance)):
        errors.append(ValidationError(
            '{} has non-unique elements'.format(instance)))
Example #16
0
def enum(validator, enum, instance, schema, errors):
    if instance not in enum:
        errors.append(ValidationError(
            '{} is not one of {}'.format(instance, enum)))
Example #17
0
def maxProperties(validator, mP, instance, schema, errors):
    if validator.is_type(instance, 'object', schema) and len(instance) > mP:
        errors.append(ValidationError(
            '{} has too many properties'.format(instance)))
Example #18
0
def minProperties(validator, mP, instance, schema, errors):
    if validator.is_type(instance, 'object', schema) and len(instance) < mP:
        errors.append(ValidationError(
            '{} does not have enough properties'.format(instance)))
Example #19
0
def _validate_and_parse_param(Validator, request, param_obj, path_matches,
                              queries, fill_by_default):
    if param_obj.get('allowEmptyValue', False):
        raise NotImplementedError  # pragma: no cover
    in_, name, schema, value = (param_obj['in'], param_obj['name'],
                                param_obj.get('schema'), None)
    style = param_obj.get('style',
                          'form' if in_ in ('query', 'cookie') else 'simple')
    explode = param_obj.get('explode', True if style == 'form' else False)
    type_tries = set()
    if not schema:
        typ = 'object'
    elif 'type' in schema:
        typ = schema['type']
    else:
        # QUICKHACK(kazuki): プリミティブ型のoneOf/anyOfのみ許容する
        def _check_subschemas(s):
            st = s.get('type')
            if st is not None:
                if st in ('integer', 'number', 'string', 'boolean'):
                    type_tries.add(st)
                    return st
                raise NotImplementedError
            ss_list = s.get('oneOf', s.get('anyOf'))
            if not ss_list:
                raise NotImplementedError
            for ss in ss_list:
                t = _check_subschemas(ss)
            return t

        typ = _check_subschemas(schema)
        if typ is None:
            raise NotImplementedError

    if style in ('matrix', 'label', 'spaceDelimited', 'pipeDelimited'):
        raise NotImplementedError  # pragma: no cover

    if in_ == 'path':
        value = path_matches[name]  # always successful
    elif in_ == 'query':
        if style == 'form' and typ == 'object' and explode:
            raise NotImplementedError  # pragma: no cover
        if style == 'deepObject':
            value = {}
            for k, v in queries.items():
                if k.startswith(name + '[') and k[-1] == ']':
                    value[k[len(name) + 1:-1]] = v[0]
            if not value:
                value = None
        else:
            if name in queries:
                value = queries[name]
                if not (style == 'form' and explode and typ == 'array'):
                    value = value[0]
            elif schema and fill_by_default and 'default' in schema:
                return {name: schema['default']}
    elif in_ == 'header' and name in request.headers:
        value = request.headers[name]
    elif in_ == 'cookie':  # pragma: no cover
        raise NotImplementedError
    if param_obj.get('required', False) and value is None:
        raise ValidationErrors(
            ValidationError(
                'required parameter "{}" is not found in {}'.format(name,
                                                                    in_)))
    if value is None:
        return {}

    if not type_tries:
        type_tries.add(typ)

    errors = []
    for typ in type_tries:
        if not isinstance(value, dict):
            try:
                value = _convert_style(style, explode, typ, value)
            except Exception as e:
                errors.append(
                    StyleError('invalid style of "{}": {}'.format(name, e)))
                continue
        if schema:
            try:
                value = _convert_type(schema, value, default_type=typ)
            except Exception as e:
                errors.append(
                    ValueError('invalid value of "{}": {}'.format(name, e)))
                continue
            try:
                value = _validate(Validator, schema, value)
            except Exception as e:
                errors.append(e)
                continue
        return {name: value}
    raise ValidationErrors(errors)
Example #20
0
def maxItems(validator, maxItems, instance, schema, errors):
    if (validator.is_type(instance, 'array', schema)
            and len(instance) > maxItems):
        errors.append(ValidationError('{} is too long'.format(instance,)))