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
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
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
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
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
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
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
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
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
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
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
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)
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)
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)
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
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)