예제 #1
0
 def validate_items(self, obj, pointer=None):
     if 'items' in self.attrs:
         items = self.attrs['items']
         if isinstance(items, Validator):
             validator = items
             for index, element in enumerate(obj):
                 with self.catch_fail():
                     obj[index] = validator(element,
                                            pointer_join(pointer,
                                                         index))  # noqa
             return obj
         elif isinstance(items, (list, tuple)):
             additionals = self.attrs['additional_items']
             validators = items
             for index, element in enumerate(obj):
                 with self.catch_fail():
                     try:
                         validator = validators[index]
                     except IndexError:
                         if additionals is True:
                             return obj
                         elif additionals is False:
                             self.fail('Additional elements are forbidden',
                                       obj, pointer_join(pointer, index))
                             continue
                         validator = additionals
                     obj[index] = validator(element,
                                            pointer_join(pointer,
                                                         index))  # noqa
             return obj
         else:
             raise NotImplementedError(items)
     return obj
예제 #2
0
 def validate_items(self, obj, pointer=None):
     if 'items' in self.attrs:
         items = self.attrs['items']
         if isinstance(items, Validator):
             validator = items
             for index, element in enumerate(obj):
                 with self.catch_fail():
                     obj[index] = validator(element, pointer_join(pointer, index))  # noqa
             return obj
         elif isinstance(items, (list, tuple)):
             additionals = self.attrs['additional_items']
             validators = items
             for index, element in enumerate(obj):
                 with self.catch_fail():
                     try:
                         validator = validators[index]
                     except IndexError:
                         if additionals is True:
                             return obj
                         elif additionals is False:
                             self.fail('Additional elements are forbidden',
                                       obj,
                                       pointer_join(pointer, index))
                             continue
                         validator = additionals
                     obj[index] = validator(element, pointer_join(pointer, index))  # noqa
             return obj
         else:
             raise NotImplementedError(items)
     return obj
예제 #3
0
파일: draft04.py 프로젝트: djta/5GCORE-1
 def validate_required(self, obj, pointer=None):
     if 'required' in self.attrs:
         for name in self.attrs['required']:
             if name not in obj:
                 self.fail('Missing property', obj,
                           pointer_join(pointer, name))  # noqa
     return obj
예제 #4
0
파일: draft04.py 프로젝트: djta/5GCORE-1
    def validate_properties(self, obj, pointer=None):
        validated = set()
        pending = set(obj.keys())
        response = {}

        if not obj:
            return response

        for name, validator in self.attrs['properties'].items():
            if name in obj:
                with self.catch_fail():
                    pending.discard(name)
                    obj[name] = validator(obj[name],
                                          pointer_join(pointer, name))  # noqa
                    validated.add(name)

        for pattern, validator in self.attrs['pattern_properties'].items():
            for name in sorted(obj.keys()):
                if re.search(pattern, name):
                    with self.catch_fail():
                        pending.discard(name)
                        obj[name] = validator(obj[name],
                                              pointer_join(pointer,
                                                           name))  # noqa
                        validated.add(name)

        if not pending:
            return obj

        additionals = self.attrs['additional_properties']
        if additionals is True:
            return obj

        if additionals is False:
            for name in pending:
                self.fail('Forbidden property', obj,
                          pointer_join(pointer, name))  # noqa
            return obj

        validator = additionals
        for name in sorted(pending):
            obj[name] = validator(obj.pop(name), pointer_join(pointer,
                                                              name))  # noqa
            validated.add(name)
        return obj
예제 #5
0
 def validate_dependencies(self, obj, pointer=None):
     for key, dependencies in self.attrs.get('dependencies', {}).items():
         if key in obj:
             if isinstance(dependencies, sequence_types):
                 for name in set(dependencies) - set(obj.keys()):
                     self.fail('Missing property', obj, pointer_join(pointer, name))  # noqa
             else:
                 dependencies(obj)
     return obj
예제 #6
0
    def validate_properties(self, obj, pointer=None):
        validated = set()
        pending = set(obj.keys())

        for name, validator in self.attrs['properties'].items():
            if name in obj:
                with self.catch_fail():
                    pending.discard(name)
                    obj[name] = validator(obj[name],
                                          pointer_join(pointer, name))  # noqa
                    validated.add(name)
            elif not validator.is_optional():
                self.fail('Required property', obj, pointer)

        for pattern, validator in self.attrs['pattern_properties'].items():
            regex = re.compile(pattern)
            for name, value in obj.items():
                if regex.search(name):
                    with self.catch_fail():
                        pending.discard(name)
                        obj[name] = validator(obj[name],
                                              pointer_join(pointer,
                                                           name))  # noqa
                        validated.add(name)

        if not pending:
            return obj

        if self.attrs['additional_properties'] is True:
            return obj

        if self.attrs['additional_properties'] is False:
            if len(obj) > len(validated):
                self.fail('Additional properties are forbidden', obj,
                          pointer)  # noqa
            return obj

        validator = self.attrs['additional_properties']
        for name, value in obj.items():
            if name not in validated:
                obj[name] = validator(value, pointer_join(pointer, name))
                validated.add(name)

        return obj
예제 #7
0
파일: draft04.py 프로젝트: djta/5GCORE-1
 def validate_dependencies(self, obj, pointer=None):
     for key, dependencies in self.attrs.get('dependencies', {}).items():
         if key in obj:
             if isinstance(dependencies, sequence_types):
                 for name in set(dependencies) - set(obj.keys()):
                     self.fail('Missing property', obj,
                               pointer_join(pointer, name))  # noqa
             else:
                 dependencies(obj)
     return obj
예제 #8
0
 def fail(self, reason, obj, pointer=None):
     """
     Called when validation fails.
     """
     pointer = pointer_join(pointer)
     err = ValidationError(reason, obj, pointer)
     if self.fail_fast:
         raise err
     else:
         self.errors.append(err)
     return err
예제 #9
0
 def fail(self, reason, obj, pointer=None):
     """
     Called when validation fails.
     """
     pointer = pointer_join(pointer)
     err = ValidationError(reason, obj, pointer)
     if self.fail_fast:
         raise err
     else:
         self.errors.append(err)
     return err
예제 #10
0
    def validate_properties(self, obj, pointer=None):
        validated = set()
        pending = set(obj.keys())

        for name, validator in self.attrs['properties'].items():
            if name in obj:
                with self.catch_fail():
                    pending.discard(name)
                    obj[name] = validator(obj[name], pointer_join(pointer, name))  # noqa
                    validated.add(name)
            elif not validator.is_optional():
                self.fail('Required property', obj, pointer)

        for pattern, validator in self.attrs['pattern_properties'].items():
            regex = re.compile(pattern)
            for name, value in obj.items():
                if regex.search(name):
                    with self.catch_fail():
                        pending.discard(name)
                        obj[name] = validator(obj[name], pointer_join(pointer, name))  # noqa
                        validated.add(name)

        if not pending:
            return obj

        if self.attrs['additional_properties'] is True:
            return obj

        if self.attrs['additional_properties'] is False:
            if len(obj) > len(validated):
                self.fail('Additional properties are forbidden', obj, pointer)  # noqa
            return obj

        validator = self.attrs['additional_properties']
        for name, value in obj.items():
            if name not in validated:
                obj[name] = validator(value, pointer_join(pointer, name))
                validated.add(name)

        return obj
예제 #11
0
    def validate_properties(self, obj, pointer=None):
        validated = set()
        pending = set(obj.keys())
        response = {}

        if not obj:
            return response

        for name, validator in self.attrs['properties'].items():
            if name in obj:
                with self.catch_fail():
                    pending.discard(name)
                    obj[name] = validator(obj[name], pointer_join(pointer, name))  # noqa
                    validated.add(name)

        for pattern, validator in self.attrs['pattern_properties'].items():
            for name in sorted(obj.keys()):
                if re.search(pattern, name):
                    with self.catch_fail():
                        pending.discard(name)
                        obj[name] = validator(obj[name], pointer_join(pointer, name))  # noqa
                        validated.add(name)

        if not pending:
            return obj

        additionals = self.attrs['additional_properties']
        if additionals is True:
            return obj

        if additionals is False:
            for name in pending:
                self.fail('Forbidden property', obj, pointer_join(pointer, name))  # noqa
            return obj

        validator = additionals
        for name in sorted(pending):
            obj[name] = validator(obj.pop(name), pointer_join(pointer, name))  # noqa
            validated.add(name)
        return obj
예제 #12
0
def compile(schema, pointer, context, scope=None):
    """
    Compiles schema with `JSON Schema`_ draft-03.

    :param schema: obj to compile
    :type schema: Mapping
    :param pointer: uri of the schema
    :type pointer: Pointer, str
    :param context: context of this schema
    :type context: Context

    .. _`JSON Schema`: http://json-schema.org
    """

    schm = deepcopy(schema)

    scope = urljoin(scope or str(pointer), schm.pop('id', None))

    if '$ref' in schema:
        return ReferenceValidator(urljoin(scope, schema['$ref']), context)

    attrs = {}

    if 'additionalItems' in schm:
        subpointer = pointer_join(pointer, 'additionalItems')
        attrs['additional_items'] = schm.pop('additionalItems')
        if isinstance(attrs['additional_items'], dict):
            compiled = compile(attrs['additional_items'], subpointer, context,
                               scope)
            attrs['additional_items'] = compiled
        elif not isinstance(attrs['additional_items'], bool):
            raise CompilationError(
                'wrong type for {}'.format('additional_items'), schema)  # noqa

    if 'additionalProperties' in schm:
        attrs['additional_properties'] = schm.pop('additionalProperties')
        if isinstance(attrs['additional_properties'], dict):
            subpointer = pointer_join(pointer, 'additionalProperties')
            value = attrs['additional_properties']
            attrs['additional_properties'] = compile(value, subpointer,
                                                     context, scope)
        elif not isinstance(attrs['additional_properties'], bool):
            raise CompilationError(
                'additionalProperties must be an object or boolean',
                schema)  # noqa

    if 'dependencies' in schm:
        attrs['dependencies'] = schm.pop('dependencies')
        if not isinstance(attrs['dependencies'], dict):
            raise CompilationError('dependencies must be an object', schema)
        for key, value in attrs['dependencies'].items():
            if isinstance(value, dict):
                subpointer = pointer_join(pointer, 'dependencies', key)
                attrs['dependencies'][key] = compile(value, subpointer,
                                                     context, scope)
            elif isinstance(value, sequence_types):
                continue
            elif not isinstance(value, string_types):
                raise CompilationError(
                    'dependencies must be an array, object or string',
                    schema)  # noqa

    if 'disallow' in schm:
        attrs['disallow'] = schm.pop('disallow')
        if isinstance(attrs['disallow'], sequence_types):
            for index, value in enumerate(attrs['disallow']):
                if isinstance(value, dict):
                    subpointer = pointer_join(pointer, 'disallow', index)
                    attrs['disallow'][index] = compile(value, subpointer,
                                                       context, scope)
                elif not isinstance(value, string_types):
                    raise CompilationError(
                        'disallow must be an object or string', schema)  # noqa
        elif not isinstance(attrs['disallow'], string_types):
            raise CompilationError('disallow must be an array or string',
                                   schema)  # noqa

    if 'divisibleBy' in schm:
        attrs['divisible_by'] = schm.pop('divisibleBy')
        if not isinstance(attrs['divisible_by'], number_types):
            raise CompilationError('divisibleBy must be a number', schema)

    if 'enum' in schm:
        attrs['enum'] = schm.pop('enum')
        if not isinstance(attrs['enum'], sequence_types):
            raise CompilationError('enum must be a sequence', schema)

    if 'exclusiveMaximum' in schm:
        attrs['exclusive_maximum'] = schm.pop('exclusiveMaximum')
        if not isinstance(attrs['exclusive_maximum'], bool):
            raise CompilationError('exclusiveMaximum must be a boolean',
                                   schema)  # noqa

    if 'exclusiveMinimum' in schm:
        attrs['exclusive_minimum'] = schm.pop('exclusiveMinimum')
        if not isinstance(attrs['exclusive_minimum'], bool):
            raise CompilationError('exclusiveMinimum must be a boolean',
                                   schema)  # noqa

    if 'extends' in schm:
        attrs['extends'] = schm.pop('extends')
        subpointer = pointer_join(pointer, 'extends')
        if isinstance(attrs['extends'], dict):
            attrs['extends'] = compile(attrs['extends'], subpointer, context,
                                       scope)
        elif isinstance(attrs['extends'], sequence_types):
            for index, value in enumerate(attrs['extends']):
                attrs['extends'][index] = compile(value, subpointer, context,
                                                  scope)
        else:
            raise CompilationError('extends must be an object or array',
                                   schema)  # noqa

    if 'format' in schm:
        attrs['format'] = schm.pop('format')
        if not isinstance(attrs['format'], string_types):
            raise CompilationError('format must be a string', schema)

    if 'items' in schm:
        subpointer = pointer_join(pointer, 'items')
        attrs['items'] = schm.pop('items')
        if isinstance(attrs['items'], (list, tuple)):
            # each value must be a json schema
            attrs['items'] = [
                compile(element, subpointer, context, scope)
                for element in attrs['items']
            ]  # noqa
        elif isinstance(attrs['items'], dict):
            # value must be a json schema
            attrs['items'] = compile(attrs['items'], subpointer, context,
                                     scope)  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('items'),
                                   schema)  # noqa

    if 'maximum' in schm:
        attrs['maximum'] = schm.pop('maximum')
        if not isinstance(attrs['maximum'], number_types):
            raise CompilationError('enum must be an integer', schema)

    if 'maxItems' in schm:
        attrs['max_items'] = schm.pop('maxItems')
        if not isinstance(attrs['max_items'], integer_types):
            raise CompilationError('maxItems must be an integer', schema)

    if 'maxLength' in schm:
        attrs['max_length'] = schm.pop('maxLength')
        if not isinstance(attrs['max_length'], integer_types):
            raise CompilationError('maxLength must be integer', schema)

    if 'minimum' in schm:
        attrs['minimum'] = schm.pop('minimum')
        if not isinstance(attrs['minimum'], number_types):
            raise CompilationError('enum must be a number', schema)

    if 'minItems' in schm:
        attrs['min_items'] = schm.pop('minItems')
        if not isinstance(attrs['min_items'], integer_types):
            raise CompilationError('minItems must be an integer', schema)

    if 'minLength' in schm:
        attrs['min_length'] = schm.pop('minLength')
        if not isinstance(attrs['min_length'], integer_types):
            raise CompilationError('minLength must be integer', schema)

    if 'pattern' in schm:
        attrs['pattern'] = schm.pop('pattern')
        if not isinstance(attrs['pattern'], string_types):
            raise CompilationError('pattern must be a string', schema)

    if 'patternProperties' in schm:
        attrs['pattern_properties'] = schm.pop('patternProperties')
        if not isinstance(attrs['pattern_properties'], dict):
            raise CompilationError('patternProperties must be an object',
                                   schema)  # noqa
        for name, value in attrs['pattern_properties'].items():
            subpointer = pointer_join(pointer, 'patternProperties', name)
            attrs['pattern_properties'][name] = compile(
                value, subpointer, context, scope)

    if 'properties' in schm:
        attrs['properties'] = schm.pop('properties')
        if not isinstance(attrs['properties'], dict):
            raise CompilationError('properties must be an object', schema)
        for name, value in attrs['properties'].items():
            subpointer = pointer_join(pointer, 'properties', name)
            attrs['properties'][name] = compile(value, subpointer, context,
                                                scope)

    if 'required' in schm:
        attrs['required'] = schm.pop('required')
        if not isinstance(attrs['required'], bool):
            raise CompilationError('required must be a boolean', schema)

    if 'type' in schm:
        attrs['type'] = schm.pop('type')
        if isinstance(attrs['type'], sequence_types):
            for index, value in enumerate(attrs['type']):
                if isinstance(value, dict):
                    subpointer = pointer_join(pointer, 'type', index)
                    attrs['type'][index] = compile(value, subpointer, context,
                                                   scope)
                elif not isinstance(value, string_types):
                    raise CompilationError('type must be an object or string',
                                           schema)  # noqa
        elif not isinstance(attrs['type'], string_types):
            raise CompilationError('type must be an array or string',
                                   schema)  # noqa

    if 'uniqueItems' in schm:
        attrs['unique_items'] = schm.pop('uniqueItems')
        if not isinstance(attrs['unique_items'], bool):
            raise CompilationError('type must be boolean', schema)

    return Draft03Validator(attrs, scope, context.formats)
예제 #13
0
def compile(schema, pointer, context, scope=None):
    """
    Compiles schema with `JSON Schema`_ draft-03.

    :param schema: obj to compile
    :type schema: Mapping
    :param pointer: uri of the schema
    :type pointer: Pointer, str
    :param context: context of this schema
    :type context: Context

    .. _`JSON Schema`: http://json-schema.org
    """

    schm = deepcopy(schema)

    scope = urljoin(scope or str(pointer), schm.pop('id', None))

    if '$ref' in schema:
        return ReferenceValidator(urljoin(scope, schema['$ref']), context)

    attrs = {}

    if 'additionalItems' in schm:
        subpointer = pointer_join(pointer, 'additionalItems')
        attrs['additional_items'] = schm.pop('additionalItems')
        if isinstance(attrs['additional_items'], dict):
            compiled = compile(attrs['additional_items'],
                               subpointer,
                               context,
                               scope)
            attrs['additional_items'] = compiled
        elif not isinstance(attrs['additional_items'], bool):
            raise CompilationError('wrong type for {}'.format('additional_items'), schema)  # noqa

    if 'additionalProperties' in schm:
        attrs['additional_properties'] = schm.pop('additionalProperties')
        if isinstance(attrs['additional_properties'], dict):
            subpointer = pointer_join(pointer, 'additionalProperties')
            value = attrs['additional_properties']
            attrs['additional_properties'] = compile(value,
                                                     subpointer,
                                                     context,
                                                     scope)
        elif not isinstance(attrs['additional_properties'], bool):
            raise CompilationError('additionalProperties must be an object or boolean', schema)  # noqa

    if 'dependencies' in schm:
        attrs['dependencies'] = schm.pop('dependencies')
        if not isinstance(attrs['dependencies'], dict):
            raise CompilationError('dependencies must be an object', schema)
        for key, value in attrs['dependencies'].items():
            if isinstance(value, dict):
                subpointer = pointer_join(pointer, 'dependencies', key)
                attrs['dependencies'][key] = compile(value,
                                                     subpointer,
                                                     context,
                                                     scope)
            elif isinstance(value, sequence_types):
                continue
            elif not isinstance(value, string_types):
                raise CompilationError('dependencies must be an array, object or string', schema)  # noqa

    if 'disallow' in schm:
        attrs['disallow'] = schm.pop('disallow')
        if isinstance(attrs['disallow'], sequence_types):
            for index, value in enumerate(attrs['disallow']):
                if isinstance(value, dict):
                    subpointer = pointer_join(pointer, 'disallow', index)
                    attrs['disallow'][index] = compile(value,
                                                       subpointer,
                                                       context,
                                                       scope)
                elif not isinstance(value, string_types):
                    raise CompilationError('disallow must be an object or string', schema)  # noqa
        elif not isinstance(attrs['disallow'], string_types):
            raise CompilationError('disallow must be an array or string', schema)  # noqa

    if 'divisibleBy' in schm:
        attrs['divisible_by'] = schm.pop('divisibleBy')
        if not isinstance(attrs['divisible_by'], number_types):
            raise CompilationError('divisibleBy must be a number', schema)

    if 'enum' in schm:
        attrs['enum'] = schm.pop('enum')
        if not isinstance(attrs['enum'], sequence_types):
            raise CompilationError('enum must be a sequence', schema)

    if 'exclusiveMaximum' in schm:
        attrs['exclusive_maximum'] = schm.pop('exclusiveMaximum')
        if not isinstance(attrs['exclusive_maximum'], bool):
            raise CompilationError('exclusiveMaximum must be a boolean', schema)  # noqa

    if 'exclusiveMinimum' in schm:
        attrs['exclusive_minimum'] = schm.pop('exclusiveMinimum')
        if not isinstance(attrs['exclusive_minimum'], bool):
            raise CompilationError('exclusiveMinimum must be a boolean', schema)  # noqa

    if 'extends' in schm:
        attrs['extends'] = schm.pop('extends')
        subpointer = pointer_join(pointer, 'extends')
        if isinstance(attrs['extends'], dict):
            attrs['extends'] = compile(attrs['extends'],
                                       subpointer,
                                       context,
                                       scope)
        elif isinstance(attrs['extends'], sequence_types):
            for index, value in enumerate(attrs['extends']):
                attrs['extends'][index] = compile(value,
                                                  subpointer,
                                                  context,
                                                  scope)
        else:
            raise CompilationError('extends must be an object or array', schema)  # noqa

    if 'format' in schm:
        attrs['format'] = schm.pop('format')
        if not isinstance(attrs['format'], string_types):
            raise CompilationError('format must be a string', schema)

    if 'items' in schm:
        subpointer = pointer_join(pointer, 'items')
        attrs['items'] = schm.pop('items')
        if isinstance(attrs['items'], (list, tuple)):
            # each value must be a json schema
            attrs['items'] = [compile(element, subpointer, context, scope) for element in attrs['items']]  # noqa
        elif isinstance(attrs['items'], dict):
            # value must be a json schema
            attrs['items'] = compile(attrs['items'], subpointer, context, scope)  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('items'), schema)  # noqa

    if 'maximum' in schm:
        attrs['maximum'] = schm.pop('maximum')
        if not isinstance(attrs['maximum'], number_types):
            raise CompilationError('enum must be an integer', schema)

    if 'maxItems' in schm:
        attrs['max_items'] = schm.pop('maxItems')
        if not isinstance(attrs['max_items'], integer_types):
            raise CompilationError('maxItems must be an integer', schema)

    if 'maxLength' in schm:
        attrs['max_length'] = schm.pop('maxLength')
        if not isinstance(attrs['max_length'], integer_types):
            raise CompilationError('maxLength must be integer', schema)

    if 'minimum' in schm:
        attrs['minimum'] = schm.pop('minimum')
        if not isinstance(attrs['minimum'], number_types):
            raise CompilationError('enum must be a number', schema)

    if 'minItems' in schm:
        attrs['min_items'] = schm.pop('minItems')
        if not isinstance(attrs['min_items'], integer_types):
            raise CompilationError('minItems must be an integer', schema)

    if 'minLength' in schm:
        attrs['min_length'] = schm.pop('minLength')
        if not isinstance(attrs['min_length'], integer_types):
            raise CompilationError('minLength must be integer', schema)

    if 'pattern' in schm:
        attrs['pattern'] = schm.pop('pattern')
        if not isinstance(attrs['pattern'], string_types):
            raise CompilationError('pattern must be a string', schema)

    if 'patternProperties' in schm:
        attrs['pattern_properties'] = schm.pop('patternProperties')
        if not isinstance(attrs['pattern_properties'], dict):
            raise CompilationError('patternProperties must be an object', schema)  # noqa
        for name, value in attrs['pattern_properties'].items():
            subpointer = pointer_join(pointer, 'patternProperties', name)
            attrs['pattern_properties'][name] = compile(value,
                                                        subpointer,
                                                        context,
                                                        scope)

    if 'properties' in schm:
        attrs['properties'] = schm.pop('properties')
        if not isinstance(attrs['properties'], dict):
            raise CompilationError('properties must be an object', schema)
        for name, value in attrs['properties'].items():
            subpointer = pointer_join(pointer, 'properties', name)
            attrs['properties'][name] = compile(value,
                                                subpointer,
                                                context,
                                                scope)

    if 'required' in schm:
        attrs['required'] = schm.pop('required')
        if not isinstance(attrs['required'], bool):
            raise CompilationError('required must be a boolean', schema)

    if 'type' in schm:
        attrs['type'] = schm.pop('type')
        if isinstance(attrs['type'], sequence_types):
            for index, value in enumerate(attrs['type']):
                if isinstance(value, dict):
                    subpointer = pointer_join(pointer, 'type', index)
                    attrs['type'][index] = compile(value,
                                                   subpointer,
                                                   context,
                                                   scope)
                elif not isinstance(value, string_types):
                    raise CompilationError('type must be an object or string', schema)  # noqa
        elif not isinstance(attrs['type'], string_types):
            raise CompilationError('type must be an array or string', schema)  # noqa

    if 'uniqueItems' in schm:
        attrs['unique_items'] = schm.pop('uniqueItems')
        if not isinstance(attrs['unique_items'], bool):
            raise CompilationError('type must be boolean', schema)

    return Draft03Validator(attrs, scope, context.formats)
예제 #14
0
파일: draft04.py 프로젝트: djta/5GCORE-1
def compile(schema, pointer, context, scope=None):
    """
    Compiles schema with `JSON Schema`_ draft-04.

    :param schema: obj to compile
    :type schema: Mapping
    :param pointer: uri of the schema
    :type pointer: Pointer, str
    :param context: context of this schema
    :type context: Context

    .. _`JSON Schema`: http://json-schema.org
    """

    schm = deepcopy(schema)

    scope = urljoin(scope or str(pointer), schm.pop('id', None))

    if '$ref' in schema:
        return ReferenceValidator(urljoin(scope, schema['$ref']), context)

    attrs = {}

    if 'additionalItems' in schm:
        subpointer = pointer_join(pointer, 'additionalItems')
        attrs['additional_items'] = schm.pop('additionalItems')
        if isinstance(attrs['additional_items'], dict):
            compiled = compile(attrs['additional_items'], subpointer, context,
                               scope)
            attrs['additional_items'] = compiled
        elif not isinstance(attrs['additional_items'], bool):
            raise CompilationError(
                'wrong type for {}'.format('additional_items'), schema)  # noqa

    if 'additionalProperties' in schm:
        subpointer = pointer_join(pointer, 'additionalProperties')
        attrs['additional_properties'] = schm.pop('additionalProperties')
        if isinstance(attrs['additional_properties'], dict):
            compiled = compile(attrs['additional_properties'], subpointer,
                               context, scope)
            attrs['additional_properties'] = compiled
        elif not isinstance(attrs['additional_properties'], bool):
            raise CompilationError(
                'wrong type for {}'.format('additional_properties'),
                schema)  # noqa

    if 'allOf' in schm:
        subpointer = pointer_join(pointer, 'allOf')
        attrs['all_of'] = schm.pop('allOf')
        if isinstance(attrs['all_of'], (list, tuple)):
            attrs['all_of'] = [
                compile(element, subpointer, context, scope)
                for element in attrs['all_of']
            ]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('allOf'),
                                   schema)  # noqa

    if 'anyOf' in schm:
        subpointer = pointer_join(pointer, 'anyOf')
        attrs['any_of'] = schm.pop('anyOf')
        if isinstance(attrs['any_of'], (list, tuple)):
            attrs['any_of'] = [
                compile(element, subpointer, context, scope)
                for element in attrs['any_of']
            ]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('anyOf'),
                                   schema)  # noqa

    if 'default' in schm:
        attrs['default'] = schm.pop('default')

    if 'dependencies' in schm:
        attrs['dependencies'] = schm.pop('dependencies')
        if not isinstance(attrs['dependencies'], dict):
            raise CompilationError('dependencies must be an object', schema)
        for key, value in attrs['dependencies'].items():
            if isinstance(value, dict):
                subpointer = pointer_join(pointer, 'dependencies', key)
                attrs['dependencies'][key] = compile(value, subpointer,
                                                     context, scope)
            elif not isinstance(value, sequence_types):
                raise CompilationError(
                    'dependencies must be an array or object', schema)  # noqa

    if 'enum' in schm:
        attrs['enum'] = schm.pop('enum')
        if not isinstance(attrs['enum'], sequence_types):
            raise CompilationError('enum must be a sequence', schema)

    if 'exclusiveMaximum' in schm:
        attrs['exclusive_maximum'] = schm.pop('exclusiveMaximum')
        if not isinstance(attrs['exclusive_maximum'], bool):
            raise CompilationError('exclusiveMaximum must be a boolean',
                                   schema)  # noqa

    if 'exclusiveMinimum' in schm:
        attrs['exclusive_minimum'] = schm.pop('exclusiveMinimum')
        if not isinstance(attrs['exclusive_minimum'], bool):
            raise CompilationError('exclusiveMinimum must be a boolean',
                                   schema)  # noqa

    if 'format' in schm:
        attrs['format'] = schm.pop('format')
        if not isinstance(attrs['format'], string_types):
            raise CompilationError('format must be a string', schema)

    if 'items' in schm:
        subpointer = pointer_join(pointer, 'items')
        attrs['items'] = schm.pop('items')
        if isinstance(attrs['items'], (list, tuple)):
            # each value must be a json schema
            attrs['items'] = [
                compile(element, subpointer, context, scope)
                for element in attrs['items']
            ]  # noqa
        elif isinstance(attrs['items'], dict):
            # value must be a json schema
            attrs['items'] = compile(attrs['items'], subpointer, context,
                                     scope)  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('items'),
                                   schema)  # noqa

    if 'maximum' in schm:
        attrs['maximum'] = schm.pop('maximum')
        if not isinstance(attrs['maximum'], number_types):
            raise CompilationError('maximum must be a number', schema)

    if 'maxItems' in schm:
        attrs['max_items'] = schm.pop('maxItems')
        if not isinstance(attrs['max_items'], integer_types):
            raise CompilationError('maxItems must be integer', schema)

    if 'maxLength' in schm:
        attrs['max_length'] = schm.pop('maxLength')
        if not isinstance(attrs['max_length'], integer_types):
            raise CompilationError('maxLength must be integer', schema)

    if 'maxProperties' in schm:
        attrs['max_properties'] = schm.pop('maxProperties')
        if not isinstance(attrs['max_properties'], integer_types):
            raise CompilationError('maxProperties must be integer', schema)

    if 'minimum' in schm:
        attrs['minimum'] = schm.pop('minimum')
        if not isinstance(attrs['minimum'], number_types):
            raise CompilationError('minimum must be a number', schema)

    if 'minItems' in schm:
        attrs['min_items'] = schm.pop('minItems')
        if not isinstance(attrs['min_items'], integer_types):
            raise CompilationError('minItems must be integer', schema)

    if 'minLength' in schm:
        attrs['min_length'] = schm.pop('minLength')
        if not isinstance(attrs['min_length'], integer_types):
            raise CompilationError('minLength must be integer', schema)

    if 'minProperties' in schm:
        attrs['min_properties'] = schm.pop('minProperties')
        if not isinstance(attrs['min_properties'], integer_types):
            raise CompilationError('minProperties must be integer', schema)

    if 'multipleOf' in schm:
        attrs['multiple_of'] = schm.pop('multipleOf')
        if not isinstance(attrs['multiple_of'], number_types):
            raise CompilationError('multipleOf must be a number', schema)

    if 'not' in schm:
        attrs['not'] = schm.pop('not')
        if not isinstance(attrs['not'], dict):
            raise CompilationError('not must be an object', schema)
        subpointer = pointer_join(pointer, 'not')
        attrs['not'] = compile(attrs['not'], subpointer, context, scope)

    if 'oneOf' in schm:
        subpointer = pointer_join(pointer, 'oneOf')
        attrs['one_of'] = schm.pop('oneOf')
        if isinstance(attrs['one_of'], (list, tuple)):
            # each value must be a json schema
            attrs['one_of'] = [
                compile(element, subpointer, context, scope)
                for element in attrs['one_of']
            ]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('oneOf'), schema)

    if 'pattern' in schm:
        attrs['pattern'] = schm.pop('pattern')
        if not isinstance(attrs['pattern'], string_types):
            raise CompilationError('pattern must be a string', schema)

    if 'properties' in schm:
        attrs['properties'] = schm.pop('properties')
        if not isinstance(attrs['properties'], dict):
            raise CompilationError('properties must be an object', schema)
        for subname, subschema in attrs['properties'].items():
            subpointer = pointer_join(pointer, subname)
            compiled = compile(subschema, subpointer, context, scope)
            attrs['properties'][subname] = compiled

    if 'patternProperties' in schm:
        attrs['pattern_properties'] = schm.pop('patternProperties')
        if not isinstance(attrs['pattern_properties'], dict):
            raise CompilationError('patternProperties must be an object',
                                   schema)  # noqa
        for subname, subschema in attrs['pattern_properties'].items():
            subpointer = pointer_join(pointer, 'patternProperties', subname)
            compiled = compile(subschema, subpointer, context, scope)
            attrs['pattern_properties'][subname] = compiled

    if 'required' in schm:
        attrs['required'] = schm.pop('required')
        if not isinstance(attrs['required'], list):
            raise CompilationError('required must be a list', schema)
        if len(attrs['required']) < 1:
            raise CompilationError('required cannot be empty', schema)

    if 'type' in schm:
        attrs['type'] = schm.pop('type')
        if isinstance(attrs['type'], string_types):
            attrs['type'] = [attrs['type']]
        elif not isinstance(attrs['type'], sequence_types):
            raise CompilationError('type must be string or sequence', schema)

    if 'uniqueItems' in schm:
        attrs['unique_items'] = schm.pop('uniqueItems')
        if not isinstance(attrs['unique_items'], bool):
            raise CompilationError('type must be boolean', schema)

    return Draft04Validator(attrs, str(pointer), context.formats)
예제 #15
0
 def validate_required(self, obj, pointer=None):
     if 'required' in self.attrs:
         for name in self.attrs['required']:
             if name not in obj:
                 self.fail('Missing property', obj, pointer_join(pointer, name))  # noqa
     return obj
예제 #16
0
def compile(schema, pointer, context, scope=None):
    """
    Compiles schema with `JSON Schema`_ draft-04.

    :param schema: obj to compile
    :type schema: Mapping
    :param pointer: uri of the schema
    :type pointer: Pointer, str
    :param context: context of this schema
    :type context: Context

    .. _`JSON Schema`: http://json-schema.org
    """

    schm = deepcopy(schema)

    scope = urljoin(scope or str(pointer), schm.pop('id', None))

    if '$ref' in schema:
        return ReferenceValidator(urljoin(scope, schema['$ref']), context)

    attrs = {}

    if 'additionalItems' in schm:
        subpointer = pointer_join(pointer, 'additionalItems')
        attrs['additional_items'] = schm.pop('additionalItems')
        if isinstance(attrs['additional_items'], dict):
            compiled = compile(attrs['additional_items'],
                               subpointer,
                               context,
                               scope)
            attrs['additional_items'] = compiled
        elif not isinstance(attrs['additional_items'], bool):
            raise CompilationError('wrong type for {}'.format('additional_items'), schema)  # noqa

    if 'additionalProperties' in schm:
        subpointer = pointer_join(pointer, 'additionalProperties')
        attrs['additional_properties'] = schm.pop('additionalProperties')
        if isinstance(attrs['additional_properties'], dict):
            compiled = compile(attrs['additional_properties'],
                               subpointer,
                               context,
                               scope)
            attrs['additional_properties'] = compiled
        elif not isinstance(attrs['additional_properties'], bool):
            raise CompilationError('wrong type for {}'.format('additional_properties'), schema)  # noqa

    if 'allOf' in schm:
        subpointer = pointer_join(pointer, 'allOf')
        attrs['all_of'] = schm.pop('allOf')
        if isinstance(attrs['all_of'], (list, tuple)):
            attrs['all_of'] = [compile(element, subpointer, context, scope) for element in attrs['all_of']]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('allOf'), schema)  # noqa

    if 'anyOf' in schm:
        subpointer = pointer_join(pointer, 'anyOf')
        attrs['any_of'] = schm.pop('anyOf')
        if isinstance(attrs['any_of'], (list, tuple)):
            attrs['any_of'] = [compile(element, subpointer, context, scope) for element in attrs['any_of']]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('anyOf'), schema)  # noqa

    if 'default' in schm:
        attrs['default'] = schm.pop('default')

    if 'dependencies' in schm:
        attrs['dependencies'] = schm.pop('dependencies')
        if not isinstance(attrs['dependencies'], dict):
            raise CompilationError('dependencies must be an object', schema)
        for key, value in attrs['dependencies'].items():
            if isinstance(value, dict):
                subpointer = pointer_join(pointer, 'dependencies', key)
                attrs['dependencies'][key] = compile(value,
                                                     subpointer,
                                                     context,
                                                     scope)
            elif not isinstance(value, sequence_types):
                raise CompilationError('dependencies must be an array or object', schema)  # noqa

    if 'enum' in schm:
        attrs['enum'] = schm.pop('enum')
        if not isinstance(attrs['enum'], sequence_types):
            raise CompilationError('enum must be a sequence', schema)

    if 'exclusiveMaximum' in schm:
        attrs['exclusive_maximum'] = schm.pop('exclusiveMaximum')
        if not isinstance(attrs['exclusive_maximum'], bool):
            raise CompilationError('exclusiveMaximum must be a boolean', schema)  # noqa

    if 'exclusiveMinimum' in schm:
        attrs['exclusive_minimum'] = schm.pop('exclusiveMinimum')
        if not isinstance(attrs['exclusive_minimum'], bool):
            raise CompilationError('exclusiveMinimum must be a boolean', schema)  # noqa

    if 'format' in schm:
        attrs['format'] = schm.pop('format')
        if not isinstance(attrs['format'], string_types):
            raise CompilationError('format must be a string', schema)

    if 'items' in schm:
        subpointer = pointer_join(pointer, 'items')
        attrs['items'] = schm.pop('items')
        if isinstance(attrs['items'], (list, tuple)):
            # each value must be a json schema
            attrs['items'] = [compile(element, subpointer, context, scope) for element in attrs['items']]  # noqa
        elif isinstance(attrs['items'], dict):
            # value must be a json schema
            attrs['items'] = compile(attrs['items'], subpointer, context, scope)  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('items'), schema)  # noqa

    if 'maximum' in schm:
        attrs['maximum'] = schm.pop('maximum')
        if not isinstance(attrs['maximum'], number_types):
            raise CompilationError('maximum must be a number', schema)

    if 'maxItems' in schm:
        attrs['max_items'] = schm.pop('maxItems')
        if not isinstance(attrs['max_items'], integer_types):
            raise CompilationError('maxItems must be integer', schema)

    if 'maxLength' in schm:
        attrs['max_length'] = schm.pop('maxLength')
        if not isinstance(attrs['max_length'], integer_types):
            raise CompilationError('maxLength must be integer', schema)

    if 'maxProperties' in schm:
        attrs['max_properties'] = schm.pop('maxProperties')
        if not isinstance(attrs['max_properties'], integer_types):
            raise CompilationError('maxProperties must be integer', schema)

    if 'minimum' in schm:
        attrs['minimum'] = schm.pop('minimum')
        if not isinstance(attrs['minimum'], number_types):
            raise CompilationError('minimum must be a number', schema)

    if 'minItems' in schm:
        attrs['min_items'] = schm.pop('minItems')
        if not isinstance(attrs['min_items'], integer_types):
            raise CompilationError('minItems must be integer', schema)

    if 'minLength' in schm:
        attrs['min_length'] = schm.pop('minLength')
        if not isinstance(attrs['min_length'], integer_types):
            raise CompilationError('minLength must be integer', schema)

    if 'minProperties' in schm:
        attrs['min_properties'] = schm.pop('minProperties')
        if not isinstance(attrs['min_properties'], integer_types):
            raise CompilationError('minProperties must be integer', schema)

    if 'multipleOf' in schm:
        attrs['multiple_of'] = schm.pop('multipleOf')
        if not isinstance(attrs['multiple_of'], number_types):
            raise CompilationError('multipleOf must be a number', schema)

    if 'not' in schm:
        attrs['not'] = schm.pop('not')
        if not isinstance(attrs['not'], dict):
            raise CompilationError('not must be an object', schema)
        subpointer = pointer_join(pointer, 'not')
        attrs['not'] = compile(attrs['not'], subpointer, context, scope)

    if 'oneOf' in schm:
        subpointer = pointer_join(pointer, 'oneOf')
        attrs['one_of'] = schm.pop('oneOf')
        if isinstance(attrs['one_of'], (list, tuple)):
            # each value must be a json schema
            attrs['one_of'] = [compile(element, subpointer, context, scope) for element in attrs['one_of']]  # noqa
        else:
            # should be a boolean
            raise CompilationError('wrong type for {}'.format('oneOf'), schema)

    if 'pattern' in schm:
        attrs['pattern'] = schm.pop('pattern')
        if not isinstance(attrs['pattern'], string_types):
            raise CompilationError('pattern must be a string', schema)

    if 'properties' in schm:
        attrs['properties'] = schm.pop('properties')
        if not isinstance(attrs['properties'], dict):
            raise CompilationError('properties must be an object', schema)
        for subname, subschema in attrs['properties'].items():
            subpointer = pointer_join(pointer, subname)
            compiled = compile(subschema, subpointer, context, scope)
            attrs['properties'][subname] = compiled

    if 'patternProperties' in schm:
        attrs['pattern_properties'] = schm.pop('patternProperties')
        if not isinstance(attrs['pattern_properties'], dict):
            raise CompilationError('patternProperties must be an object', schema)  # noqa
        for subname, subschema in attrs['pattern_properties'].items():
            subpointer = pointer_join(pointer, 'patternProperties', subname)
            compiled = compile(subschema, subpointer, context, scope)
            attrs['pattern_properties'][subname] = compiled

    if 'required' in schm:
        attrs['required'] = schm.pop('required')
        if not isinstance(attrs['required'], list):
            raise CompilationError('required must be a list', schema)
        if len(attrs['required']) < 1:
            raise CompilationError('required cannot be empty', schema)

    if 'type' in schm:
        attrs['type'] = schm.pop('type')
        if isinstance(attrs['type'], string_types):
            attrs['type'] = [attrs['type']]
        elif not isinstance(attrs['type'], sequence_types):
            raise CompilationError('type must be string or sequence', schema)

    if 'uniqueItems' in schm:
        attrs['unique_items'] = schm.pop('uniqueItems')
        if not isinstance(attrs['unique_items'], bool):
            raise CompilationError('type must be boolean', schema)

    return Draft04Validator(attrs, str(pointer), context.formats)