def patternProperties(validator, patternProperties, instance, schema): if not validator.is_type(instance, "object"): return for pattern, subschema in iteritems(patternProperties): for k, v in iteritems(instance): if re.search(pattern, k): for error in validator.descend(v, subschema, path=k, schema_path=pattern): yield error
def json2schema(node, name=None, path=(), check_value=True): """Return a strict validation schema for the given JSON node""" node_type = type(node) if node_type not in reversed_types: for type_, schemta in iteritems(reversed_types): if isinstance(node, type_): reversed_types[node_type] = schemta break else: raise DTDSchemaError("Unexpected type %s at path %s" % (node_type, path), instance=node, path=path) schema = DEFAULT_SCHEMA_NODE.copy() schema['type'] = reversed_types[node_type] if schema['type'] == 'array': length = len(node) if length: sub_schemas = [] sub_path = get_subpath(name, path) sub_types = set() for sub_node in node: sub_schema = json2schema(sub_node, path=sub_path, check_value=False) sub_types.add(sub_schema['type']) sub_schemas.append(sub_schema) if not sub_types.intersection(['array', 'object']): if check_value: schema['value'] = node sub_schemas = [{'type': _type} for _type in sub_types] schema['items'] = {'anyOf': sub_schemas} schema['maxItems'] = schema['minItems'] = length else: schema['value'] = node schema['minItems'] = 0 schema['additionalItems'] = False elif schema['type'] == 'object': sub_items = [] sub_path = get_subpath(name, path) for sub_name, sub_node in iteritems(node): sub_items.append((sub_name, json2schema(sub_node, sub_name, sub_path, check_value=check_value))) if sub_items: properties = {} for sub_name, sub_schema in sub_items: properties[sub_name] = sub_schema schema['properties'] = properties schema['required'] = list(properties) schema['additionalProperties'] = False elif check_value: schema['value'] = node return schema
def patternProperties(validator, patternProperties, instance, schema): if not validator.is_type(instance, "object"): return for pattern, subschema in iteritems(patternProperties): for k, v in iteritems(instance): if re.search(pattern, k): for error in validator.descend( v, subschema, path=k, schema_path=pattern, ): yield error
def build_classes(self, strict=False): """ Args: strict: use this to validate required fields while creating the class Returns: """ builder = classbuilder.ClassBuilder(self.resolver) for nm, defn in iteritems(self.schema.get('definitions', {})): uri = util.resolve_ref_uri(self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn) nm = self.schema['title'] if 'title' in self.schema else self.schema[ 'id'] nm = inflection.parameterize(six.text_type(nm), '_') kw = {"strict": strict} builder.construct(nm, self.schema, **kw) self._resolved = builder.resolved return (util.Namespace.from_mapping( dict((inflection.camelize(uri.split('/')[-1]), klass) for uri, klass in six.iteritems(builder.resolved))))
def _generate_legacy_type_checks(types=()): """ Generate newer-style type checks out of JSON-type-name-to-type mappings. Arguments: types (dict): A mapping of type names to their Python types Returns: A dictionary of definitions to pass to `TypeChecker` """ types = dict(types) def gen_type_check(pytypes): pytypes = _utils.flatten(pytypes) def type_check(checker, instance): if isinstance(instance, bool): if bool not in pytypes: return False return isinstance(instance, pytypes) return type_check definitions = {} for typename, pytypes in iteritems(types): definitions[typename] = gen_type_check(pytypes) return definitions
def dependencies(validator, dependencies, instance, schema): if not validator.is_type(instance, "object"): return for property, dependency in iteritems(dependencies): if property not in instance: continue if dependency is True: dependency = {} elif dependency is False: dependency = {"not": {}} if validator.is_type(dependency, "object"): for error in validator.descend( instance, dependency, schema_path=property, ): yield error else: dependencies = _utils.ensure_list(dependency) for dependency in dependencies: if dependency not in instance: yield ValidationError( "%r is a dependency of %r" % (dependency, property) )
def evaluate(self, instance, _schema=None): obj = {} if _schema is None: _schema = self.schema if _schema is True: return obj if _schema is False: return obj scope = id_of(_schema) if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue subobj = validator().evaluate(self, v, instance, _schema) _utils.merge(obj, subobj) finally: if scope: self.resolver.pop_scope() return obj
def __init__( self, base_uri, referrer, store=(), cache_remote=True, handlers=(), urljoin_cache=None, remote_cache=None, ): if urljoin_cache is None: urljoin_cache = lru_cache(1024)(urljoin) if remote_cache is None: remote_cache = lru_cache(1024)(self.resolve_from_url) self.referrer = referrer self.cache_remote = cache_remote self.handlers = dict(handlers) self._scopes_stack = [base_uri] self.store = _utils.URIDict( (id, validator.META_SCHEMA) for id, validator in iteritems(meta_schemas) ) self.store.update(store) self.store[base_uri] = referrer self._urljoin_cache = urljoin_cache self._remote_cache = remote_cache
def _generate_legacy_type_checks(types=()): """ Generate type check definitions suitable for TypeChecker.redefine_many, using the supplied types. Type Checks are simple isinstance checks, except checking that numbers aren't really bools. Arguments: types (dict): A mapping of type names to their Python Types Returns: A dictionary of definitions to pass to TypeChecker """ types = dict(types) def gen_type_check(pytypes): pytypes = _utils.flatten(pytypes) def type_check(checker, instance): if isinstance(instance, bool): if bool not in pytypes: return False return isinstance(instance, pytypes) return type_check definitions = {} for typename, pytypes in iteritems(types): definitions[typename] = gen_type_check(pytypes) return definitions
def build_classes(self,strict=False): """ Args: strict: use this to validate required fields while creating the class Returns: """ builder = classbuilder.ClassBuilder(self.resolver) for nm, defn in iteritems(self.schema.get('definitions', {})): uri = util.resolve_ref_uri( self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn) nm = self.schema['title'] if 'title' in self.schema else self.schema['id'] nm = inflection.parameterize(six.text_type(nm), '_') kw = {"strict" : strict} builder.construct(nm, self.schema,**kw) self._resolved = builder.resolved return ( util.Namespace.from_mapping(dict( (inflection.camelize(uri.split('/')[-1]), klass) for uri, klass in six.iteritems(builder.resolved))) )
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema with self.resolver.in_scope(_schema.get(u"id", u"")): ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error
def total_errors(self): """ The total number of errors in the entire tree, including children. """ child_errors = sum(len(tree) for _, tree in iteritems(self._contents)) return len(self.errors) + child_errors
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema scope = _schema.get(u"id") if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
def __init__( self, base_uri, referrer, store=(), cache_remote=True, handlers=(), urljoin_cache=None, remote_cache=None, ): if urljoin_cache is None: urljoin_cache = lru_cache(1024)(urljoin) if remote_cache is None: remote_cache = lru_cache(1024)(self.resolve_from_url) self.referrer = referrer self.cache_remote = cache_remote self.handlers = dict(handlers) self._scopes_stack = [base_uri] self.store = _utils.URIDict( (id, validator.META_SCHEMA) for id, validator in iteritems(meta_schemas)) self.store.update(store) self.store[base_uri] = referrer self._urljoin_cache = urljoin_cache self._remote_cache = remote_cache
def build_classes(self, strict=False, named_only=False, standardize_names=True): """ Build all of the classes named in the JSONSchema. Class names will be transformed using inflection by default, so names with spaces in the schema will be camelcased, while names without spaces will have internal capitalization dropped. Thus "Home Address" becomes "HomeAddress", while "HomeAddress" becomes "Homeaddress" To disable this behavior, pass standardize_names=False, but be aware that accessing names with spaces from the namespace can be problematic. Args: strict: (bool) use this to validate required fields while creating the class named_only: (bool) If true, only properties with an actual title attribute will be included in the resulting namespace (although all will be generated). standardize_names: (bool) If true (the default), class names will be tranformed by camel casing Returns: A namespace containing all the generated classes """ kw = {"strict": strict} builder = classbuilder.ClassBuilder(self.resolver) for nm, defn in iteritems(self.schema.get('definitions', {})): uri = python_jsonschema_objects.util.resolve_ref_uri( self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn, **kw) if standardize_names: def name_transform(t): return inflection.camelize( inflection.parameterize(six.text_type(t), '_')) else: def name_transform(t): return t nm = self.schema['title'] if 'title' in self.schema else self.schema[ 'id'] nm = inflection.parameterize(six.text_type(nm), '_') builder.construct(nm, self.schema, **kw) self._resolved = builder.resolved classes = {} for uri, klass in six.iteritems(builder.resolved): title = getattr(klass, '__title__', None) if title is not None: classes[name_transform(title)] = klass elif not named_only: classes[name_transform(uri.split('/')[-1])] = klass return python_jsonschema_objects.util.Namespace.from_mapping(classes)
def properties_draft4(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return for property, subschema in iteritems(properties): if property in instance: for error in validator.descend(instance[property], subschema, path=property, schema_path=property): yield error
def normalize(cls, validator, value, instance, schema): r"""Normalization method for 'properties' container property.""" if not isinstance(instance, dict): return instance for property, subschema in iteritems(value): if property not in instance: instance[property] = normalizer_mod.UndefinedProperty() return instance
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema if _schema is True: return elif _schema is False: yield exceptions.ValidationError( "False schema does not allow %r" % (instance, ), validator=None, validator_value=None, instance=instance, schema=_schema, ) return scope = id_of(_schema) if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue if PY36 and inspect.isasyncgenfunction(validator): bp = AsyncValidationBreakpoint( coroutine=validator, value=v, validator=k, validator_value=v, instance=instance, schema=_schema, ) yield bp errors = bp.errors else: errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
def __init__(self, base_uri, referrer, store=(), cache_remote=True, handlers=()): self.base_uri = base_uri self.resolution_scope = base_uri # This attribute is not used, it is for backwards compatibility self.referrer = referrer self.cache_remote = cache_remote self.handlers = dict(handlers) self.store = _utils.URIDict((id, validator.META_SCHEMA) for id, validator in iteritems(meta_schemas)) self.store.update(store) self.store[base_uri] = referrer
def build_classes(self): builder = classbuilder.ClassBuilder(self.resolver) for k, v in iteritems(self.schema): if k == 'definitions': for nm, defn in iteritems(v): uri = util.resolve_ref_uri( self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn) nm = self.schema['title'] if 'title' in self.schema else self.schema['id'] nm = inflection.parameterize(six.text_type(nm), '_') builder.construct(nm, self.schema) return ( util.Namespace.from_mapping(dict( (inflection.camelize(uri.split('/')[-1]), klass) for uri, klass in six.iteritems(builder.resolved))) )
def build_classes(self): builder = classbuilder.ClassBuilder(self.resolver) for k, v in iteritems(self.schema): if k == 'definitions': for nm, defn in iteritems(v): uri = util.resolve_ref_uri( self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn) nm = self.schema['title'] if 'title' in self.schema else self.schema['id'] nm = inflection.parameterize(unicode(nm), '_') builder.construct(nm, self.schema) return ( util.Namespace.from_mapping(dict( (inflection.camelize(uri.split('/')[-1]), klass) for uri, klass in builder.resolved.iteritems())) )
def properties_draft4(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return for property, subschema in iteritems(properties): if property in instance: for error in validator.descend( instance[property], subschema, path=property, schema_path=property, ): yield error
def build_classes(self,strict=False, named_only=False, standardize_names=True): """ Build all of the classes named in the JSONSchema. Class names will be transformed using inflection by default, so names with spaces in the schema will be camelcased, while names without spaces will have internal capitalization dropped. Thus "Home Address" becomes "HomeAddress", while "HomeAddress" becomes "Homeaddress" To disable this behavior, pass standardize_names=False, but be aware that accessing names with spaces from the namespace can be problematic. Args: strict: (bool) use this to validate required fields while creating the class named_only: (bool) If true, only properties with an actual title attribute will be included in the resulting namespace (although all will be generated). standardize_names: (bool) If true (the default), class names will be tranformed by camel casing Returns: A namespace containing all the generated classes """ kw = {"strict": strict} builder = classbuilder.ClassBuilder(self.resolver) for nm, defn in iteritems(self.schema.get('definitions', {})): uri = python_jsonschema_objects.util.resolve_ref_uri( self.resolver.resolution_scope, "#/definitions/" + nm) builder.construct(uri, defn, **kw) if standardize_names: name_transform = lambda t: inflection.camelize(inflection.parameterize(six.text_type(t), '_')) else: name_transform = lambda t: t nm = self.schema['title'] if 'title' in self.schema else self.schema['$id'] nm = inflection.parameterize(six.text_type(nm), '_') builder.construct(nm, self.schema,**kw) self._resolved = builder.resolved classes = {} for uri, klass in six.iteritems(builder.resolved): title = getattr(klass, '__title__', None) if title is not None: classes[name_transform(title)] = klass elif not named_only: classes[name_transform(uri.split('/')[-1])] = klass return python_jsonschema_objects.util.Namespace.from_mapping(classes)
def properties_draft3(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return for property, subschema in iteritems(properties): if property in instance: for error in validator.descend(instance[property], subschema, path=property, schema_path=property): yield error elif subschema.get("required", False): error = ValidationError("%r is a required property" % property) error._set(validator="required", validator_value=subschema["required"], instance=instance, schema=schema) error.path.appendleft(property) error.schema_path.extend([property, "required"]) yield error
def __init__( self, base_uri, referrer, store=(), cache_remote=True, handlers=(), ): self.base_uri = base_uri self.resolution_scope = base_uri # This attribute is not used, it is for backwards compatibility self.referrer = referrer self.cache_remote = cache_remote self.handlers = dict(handlers) self.store = _utils.URIDict( (id, validator.META_SCHEMA) for id, validator in iteritems(meta_schemas) ) self.store.update(store) self.store[base_uri] = referrer
def dependencies(validator, dependencies, instance, schema): if not validator.is_type(instance, "object"): return for property, dependency in iteritems(dependencies): if property not in instance: continue if validator.is_type(dependency, "object"): for error in validator.descend(instance, dependency, schema_path=property): yield error else: dependencies = _utils.ensure_list(dependency) for dependency in dependencies: if dependency not in instance: yield ValidationError("%r is a dependency of %r" % (dependency, property))
def validate_properties(validator, properties, instance, schema): if instance is None and (schema.get('x-nullable') is True or schema.get('nullable')): return if not validator.is_type(instance, "object"): return for property, subschema in iteritems(properties): if property in instance: for error in validator.descend( instance[property], subschema, path=property, schema_path=property, ): yield error
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema if _schema is True: return elif _schema is False: yield exceptions.ValidationError( "False schema does not allow %r" % (instance,), validator=None, validator_value=None, instance=instance, schema=_schema, ) return scope = id_of(_schema) if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema if _schema is True: return elif _schema is False: yield exceptions.ValidationError( "False schema does not allow %r" % (instance, ), validator=None, validator_value=None, instance=instance, schema=_schema, ) return scope = id_of(_schema) if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k not in {u"if", u"$ref"}: error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema # =============== tuanmd modified self.instance_data = instance # ======================= scope = _schema.get(u"id") if scope: self.resolver.push_scope(scope) try: # ref = _schema.get(u"$ref") # if ref is not None: # validators = [] # for schema_key in _schema: # if schema_key == "$ref": # validators.append((u"$ref", ref)) # else: # validators.append((schema_key, _schema[schema_key])) # else: # validators = iteritems(_schema) validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue # =============== tuanmd modified k, v = self.convertData(validator, instance, k, v) # ======================= errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
def dependencies(validator, dependencies, instance, schema): if not validator.is_type(instance, "object"): return for property, dependency in iteritems(dependencies): if property not in instance: continue if validator.is_type(dependency, "array"): for each in dependency: if each not in instance: message = "%r is a dependency of %r" yield ValidationError(message % (each, property)) else: for error in validator.descend( instance, dependency, schema_path=property, ): yield error
def properties_draft3(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return for property, subschema in iteritems(properties): if property in instance: for error in validator.descend( instance[property], subschema, path=property, schema_path=property, ): yield error elif subschema.get("required", False): error = ValidationError("%r is a required property" % property) error._set( validator="required", validator_value=subschema["required"], instance=instance, schema=schema, ) error.path.appendleft(property) error.schema_path.extend([property, "required"]) yield error
def create_dereffing_validator(instance_resolver): """Create a customized Draft4Validator that follows $refs in the schema being validated (the Swagger spec for a service). This is not to be confused with $refs that are in the schema that describes the Swagger 2.0 specification. :param instance_resolver: resolver for the swagger service's spec :type instance_resolver: :class:`jsonschema.RefResolver` :rtype: Its complicated. See jsonschema.validators.create() """ visited_refs = {} validators_to_bound = { '$ref', 'additionalProperties', 'allOf', 'anyOf', 'dependencies', 'maxProperties', 'minProperties', 'not', 'oneOf', 'patternProperties', 'properties', 'required', 'type', } bound_validators = { k: functools.partial( validator_wrapper, instance_resolver=instance_resolver, visited_refs=visited_refs, default_validator_callable=v, ) if k in validators_to_bound else v for k, v in iteritems(Draft4Validator.VALIDATORS) } return validators.extend(Draft4Validator, bound_validators)
def create_dereffing_validator(instance_resolver): """Create a customized Draft4Validator that follows $refs in the schema being validated (the Swagger spec for a service). This is not to be confused with $refs that are in the schema that describes the Swagger 2.0 specification. :param instance_resolver: resolver for the swagger service's spec :type instance_resolver: :class:`jsonschema.RefResolver` :rtype: Its complicated. See jsonschema.validators.create() """ visited_refs = {} custom_validators = { '$ref': _validators.ref, 'properties': _validators.properties_draft4, 'additionalProperties': _validators.additionalProperties, 'patternProperties': _validators.patternProperties, 'type': _validators.type_draft4, 'dependencies': _validators.dependencies, 'required': _validators.required_draft4, 'minProperties': _validators.minProperties_draft4, 'maxProperties': _validators.maxProperties_draft4, 'allOf': _validators.allOf_draft4, 'oneOf': _validators.oneOf_draft4, 'anyOf': _validators.anyOf_draft4, 'not': _validators.not_draft4, } bound_validators = {} for k, v in iteritems(custom_validators): bound_validators[k] = functools.partial( validator_wrapper, instance_resolver=instance_resolver, visited_refs=visited_refs, default_validator_callable=v) return validators.extend(Draft4Validator, bound_validators)
def _set(self, **kwargs): for k, v in iteritems(kwargs): if getattr(self, k) is _unset: setattr(self, k, v)
{'type': 'string'}, {'type': 'number'}, {'type': 'array'}, ], } draft4_validators_ext = Draft4Validator.VALIDATORS.copy() draft4_validators_ext['value'] = _value ExtDraft4Validator = create(draft4_schema_ext, draft4_validators_ext) default_validator = ExtDraft4Validator({}) # reverse type map from Python to JSON schema reversed_types = {} for schema, types in iteritems(ExtDraft4Validator.DEFAULT_TYPES): if isinstance(types, (tuple, list)): for type_ in types: reversed_types[type_] = schema else: reversed_types[types] = schema DEFAULT_SCHEMA_NODE = {} def get_subnode(root, path): node = root for step in path: node = node[step] return node