def _validate_if(self, value, schema, constraint, path): if is_object(constraint): error = self._validate(value, constraint, path) key = 'then' if error is None else 'else' constraint = schema[key] if key in schema else None if is_object(constraint): return self._validate(value, constraint, path)
def _validate_property_names(self, value, _, constraint, path): if is_object(value) and is_object(constraint): for name in value.keys(): name = str(name) child_path = f'{path}/{name}' error = self._validate(name, constraint, child_path) if error is not None: return error
def _fully_qualify_refs(self, dictionary, url): for key, value in dictionary.items(): if key == '$ref': if value.startswith('#'): dictionary[key] = url + value elif is_object(value): self._fully_qualify_refs(value, url) elif is_array(value): for item in value: if is_object(item): self._fully_qualify_refs(item, url)
def _validate_dependencies(self, value, schema, constraint, path): if is_object(value) and is_object(constraint): for name, child_constraint in constraint.items(): if name in value: if is_array(child_constraint): for required in child_constraint: if required not in value: return f"the {name} property requires the {required} property but it is missing." elif is_object(child_constraint): error = self._validate(value, child_constraint, path) if error is not None: return error
def _validate_contains(self, value, _, constraint, path): if is_array(value) and is_object(constraint): for index, item in enumerate(value): error = self._validate(item, constraint, f'{path}[{index}]') if error is None: return None return 'the array does not contain any item that satisfies the contains schema.'
def _validate_type(self, value, schema, constraint, path): if isinstance(constraint, list): for possible_type in constraint: if self._validate_type(value, schema, possible_type, path) is None: return None return f'it is not one of {str(constraint).replace("None", "null")}' elif constraint == 'object': if not is_object(value): return 'it is not an object.' elif constraint == 'array': if not is_array(value): return 'it is not an array.' elif constraint == 'string': if not is_string(value): return 'it is not a string.' elif constraint == 'integer': if not is_integer(value): return 'it is not an integer.' elif constraint == 'number': if not is_number(value): return 'it is not a number.' elif constraint == 'boolean': if not is_boolean(value): return 'it is not a boolean.' elif constraint == 'null' or constraint is None: if value is not None: return 'it is not null.'
def test_is_object(self): assert is_object(True) is False assert is_number(False) is False assert is_object(0) is False assert is_object(0.0) is False assert is_object('Bob') is False assert is_object([1]) is False assert is_object((1,)) is False assert is_object({}) is True assert is_object(OrderedDict()) is True
def _handle_item_validation(self, value, schema, constraint, path): if (is_object(constraint) or is_array(constraint)) and is_array(value): additional = self._get_additional_schema('additionalItems', schema) for index in range(len(value)): if is_object(constraint): schema = constraint elif index < len(constraint): schema = constraint[index] else: schema = additional if schema is None: return f'entry {index} in the array is not allowed here.' error = self._validate(value[index], schema, f'{path}[{index}]') if error is not None: return error
def _handle_property_validation(self, value, specific_props, pattern_props, additional_props, path): if not is_object(value): return None error = None for name, child in value.items(): name = str(name) child_path = f'{path}/{name}' schema = None if name in specific_props: schema = specific_props[name] else: for pattern in pattern_props.keys(): if re.match(pattern, name): schema = pattern_props[pattern] break if schema is None: schema = additional_props if schema is None: return f'the {name} property is not allowed here.' error = self._validate(child, schema, child_path) if error is None: if path in self._extension_cache: # noinspection PyProtectedMember error = self._validate(child, self._extension_cache[path]._schema, child_path) elif name in self._extension_cache: # noinspection PyProtectedMember error = self._validate(child, self._extension_cache[name]._schema, child_path) if error is not None: break return error
def _validate__ref(self, value, schema, constraint, path): document = self._schema url, ref_path = urldefrag(constraint) # Pull external resource if url: if url not in self._ref_cache: document = _schema_reader(url) self._fully_qualify_refs(document, url) self._ref_cache[url] = document else: document = self._ref_cache[url] schema = find_value(document, ref_path) if schema is None: return f'the reference, \'{constraint}\', does not refer to anything.' if not is_object(schema): return f'the reference, \'{constraint}\', does not refer to a schema.' return self._validate(value, schema, path)
def _validate_not(self, value, schema, constraint, path): if is_object(constraint): error = self._validate(value, constraint, path) return 'the value was accepted by the child schema.' if error is None else None
def _validate_max_properties(self, value, schema, constraint, path): if is_object(value) and is_number(constraint): if len(value) > constraint: # noinspection SpellCheckingInspection return f'the object can have no more than {constraint} propert{"y" if constraint == 1 else "ies"}.'
def _validate_min_properties(self, value, schema, constraint, path): if is_object(value) and is_number(constraint): if len(value) < constraint: # noinspection SpellCheckingInspection return f'the object needs at least {constraint} propert{"y" if constraint == 1 else "ies"}.'
def _validate_required(self, value, schema, constraint, path): if is_object(value) and is_array(constraint): for required in constraint: if required not in value: return f'it is missing the {required} property.'