def check_schema_base_path(): if not _SCHEMA_BASE_PATH: raise SchemaError( "Make sure to first set _SCHEMA_BASE_PATH (base_path) to the location of the json/yaml " "file to process.") if not _SCHEMA_BASE_URI: raise SchemaError( "Make sure to first set _SCHEMA_BASE_URI (base_uri) to the location of the json/yaml " "file to process, and _SCHEMA_BASE_URI to the corresponding URI.")
def load_schema(schema, schemas_store=None): _(""" Load a schema to the schema store. if no schema store is provided, only the internal schema store is filled. :param schema: schema as dictionary :type schema: dict :param schemas_store: optional schemas_store to fill :type schemas_store: dict """) from ngoschema.resolvers.uri_resolver import UriResolver uri = _id_of(schema).rstrip('#') if not uri and "title" in schema: uri = inflection.parameterize(six.text_type(schema["title"]), "_") if not uri: raise SchemaError( "Impossible to load schema because `id (or `$id) and `title fields" "are missing.\n%s" % schema) if schemas_store is not None: if schema != schemas_store.get(uri, schema): logger.info( "Overwriting a different schema '%s' is already registered in schema store." % uri) schemas_store[uri] = schema # add to main registry UriResolver.register_doc(schema, uri) return uri, schema
def wrapper(self, *method_args, **method_kwargs): logging.debug("JSON Schema for %s -> %s", self.request.method, self.__class__) try: json_req = json.loads(self.request.body) if schema is not None: logging.debug("Validating json schema") validate(json_req, schema) elif self.request.method not in ["GET", "HEAD", "DELETE"]: raise SchemaError("Request method %s must have a schema" % self.request.method) else: logging.debug("No json schema for request, skipping") return method(self, json_req, *method_args, **method_kwargs) except (ValidationError, ValidationError) as error: self.set_status(BAD_REQUEST) self.write({"error": str(error)}) self.finish() except SchemaError as error: self.set_status(BAD_REQUEST) if options.debug: logging.exception("Request triggered exception") self.write({"error": str(error)}) else: self.write( {"error": "JSON request not formatted properly"}) self.finish()
def discriminator_validator(validator, oneOf, instance, schema): discriminator = schema.get('discriminator') propertyName = discriminator['propertyName'] mapping = discriminator['mapping'] errs = list( validator.descend( instance, { 'type': 'object', 'properties': { propertyName: { 'type': 'string', 'enum': list(mapping), }, }, 'required': [propertyName], }, )) if errs: yield errs[0] return descr_value = instance[propertyName] descr_schema = mapping[descr_value] for index, subschema in enumerate(oneOf): if subschema == descr_schema: break else: yield SchemaError('descriminator error') return yield from validator.descend(instance, subschema, schema_path=index)
def check_json_matches_schema(jsondata, schema_filename: str, base_path: str = "", base_uri: str = ""): """ Check the given json data against the jsonschema in the given schema file, raising an exception on error. The exception text includes one or more validation error messages. schema_filename is relative to the schema root directory. may raise SchemaError or ValidationError """ set_schema_base_path(base_path=base_path, base_uri=base_uri) try: validator = Validator(_load_json_schema(schema_filename)) except SchemaError as e: raise SchemaError('{} is invalid: {}'.format(schema_filename, e)) err_msg_l = [] for error in validator.iter_errors(jsondata): err_msg_l.append('{}: {}'.format( ' '.join([str(word) for word in error.path]), error.message)) if err_msg_l: raise ValidationError(' + '.join(err_msg_l)) else: return True
def wrapper(self, *method_args, **method_kwargs): try: if schema is not None: schema["additionalProperties"] = False validate(self.api_request, schema) elif self.request.method not in ["GET", "HEAD", "DELETE"]: raise SchemaError("Request method %s must have a schema" % self.request.method) return method(self, *method_args, **method_kwargs) except (JsonValidationError, ValidationError) as error: self.set_status(BAD_REQUEST) self.write({"error": str(error)}) self.finish() except SchemaError as error: self.set_status(BAD_REQUEST) if options.debug: logging.exception('Request triggered exception') self.write({"error": "JSON schema: " + str(error)}) else: self.write( {"error": "JSON request not formatted properly"}) self.finish() except StatementError: self.set_status(BAD_REQUEST) logging.exception('Request triggered exception') self.write({"error": "JSON request not formatted properly"}) self.finish()
def check_schema(schema: dict) -> None: """ Throws an exception if the schema is not a valid instance of the JSON Schema specification. The schema can (and should) specify which draft of JSON Schema it follows using the reserved keyword "$schema" [1]. Supports drafts 4, 6 and 7 of JSON Schema [2]. If not specified, the check is performed against draft 7, the newest version at the time of writing this module. Parameters ---------- schema : dict The schema to be checked. References ---------- [1] : https://json-schema.org/understanding-json-schema/basics.html#declaring-a-json-schema [2] : https://json-schema.org/understanding-json-schema/reference/schema.html#schema """ specification = schema.get("$schema", None) if specification == "http://json-schema.org/draft-07/schema#": jsonschema.Draft7Validator.check_schema(schema=schema) elif specification == "http://json-schema.org/draft-06/schema#": jsonschema.Draft6Validator.check_schema(schema=schema) elif specification == "http://json-schema.org/draft-04/schema#": jsonschema.Draft4Validator.check_schema(schema=schema) elif specification is None: # Default to draft 7 if unspecified jsonschema.Draft7Validator.check_schema(schema=schema) else: # Throw exception if specified but not supported raise SchemaError( f"JSON Schema specification ({specification}) is not supported." )
def validate_against(self, instance, schemauris=[], strict=False): """ validate the instance against each of the schemas identified by the list of schemauris. For the instance to be considered valid, it must validate against each of the named schemas. $extensionSchema properties within the instance are ignored. :argument instance: a parsed JSON document to be validated. :argument list schemauris: a list of URIs of the schemas to validate against. :argument bool strict: if True, validation will fail if any of the schema URIs cannot be resolved to a schema. if False, unresolvable schemas URIs will be ignored and validation against that schema will be skipped. """ if isinstance(schemauris, str) or isinstance(schemauris, unicode): schemauris = [ schemauris ] schema = None out = True for uri in schemauris: val = self._validators.get(uri) if not val: (urib,frag) = self._spliturifrag(uri) schema = self._schemaStore.get(urib) if not schema: try: schema = self._loader(urib) except KeyError, e: if strict: raise SchemaError("Unable to resolve schema for " + urib) continue resolver = jsch.RefResolver(uri, schema, self._schemaStore, handlers=self._handler) if frag: try: schema = resolver.resolve_fragment(schema, frag) except RefResolutionError, ex: raise SchemaError("Unable to resolve fragment, "+frag+ "from schema, "+ urib) cls = jsch.validator_for(schema) cls.check_schema(schema) val = cls(schema, resolver=resolver)
def __init__(self, schema, types=(), resolver=None, format_checker=None, skip_meta_validation=False): super(PandelVisitor, self).__init__(schema, types, resolver, format_checker) self._types.update({ "number": ( numbers.Number, np.number ), ## type(np.nan) == builtins.float! FIXME, are numpy-numbers --> json-types OK?? "integer": (int, np.integer), "boolean": (bool, np.bool_), #, np.bool8), "array": (list, tuple, np.ndarray), "object": (dict, pd.DataFrame, pd.Series) }) ## Setup Draft4/3 validation # # Meta-validate schema # with original validators (and not self) # because this class inherits an empty (schema/rules) validator. validator_class = jsonschema.validators.validator_for( schema) ## Falls back to 'Draft4' if no `$schema` exists. self.VALIDATORS = validator_class.VALIDATORS.copy() self.META_SCHEMA = validator_class.META_SCHEMA self.VALIDATORS.update({ 'items': PandelVisitor._rule_items, 'additionalProperties': PandelVisitor._rule_additionalProperties, 'additionalItems': PandelVisitor._rule_additionalItems, }) if validator_class == Draft3Validator: self.VALIDATORS.update({ 'properties': PandelVisitor._rule_properties_draft3, }) else: self.VALIDATORS.update({ 'properties': PandelVisitor._rule_properties_draft4, 'required': PandelVisitor._rule_required_draft4, }) self.old_scopes = [] ## Cannot use ``validator_class.check_schema()`` because # need to relay my args to ``validator_class.__init__()``. # Even better use myself, that i'm fatser (kind of...). if not skip_meta_validation: for error in self.iter_errors(schema, validator_class.META_SCHEMA): raise SchemaError.create_from(error)
def load_schema(filename: Path) -> Dict: with open(filename, 'r') as f: try: if filename.suffix == '.json': data = json.load(f) return data elif filename.suffix == '.yaml': data = yaml.safe_load(f) return data except Exception as e: logger.debug(e) raise SchemaError("Schema not saved in a known format") return {}
def _get_ssh_key(self, key): key_fileobj = StringIO(key) key_algorithms = [ paramiko.RSAKey, paramiko.Ed25519Key, ] for key_algo in key_algorithms: try: return getattr(key_algo, 'from_private_key')(key_fileobj) except (paramiko.ssh_exception.SSHException, ValueError): key_fileobj.seek(0) continue else: raise SchemaError( _('Unrecognized or unsupported SSH key algorithm, ' 'only RSA and ED25519 are currently supported.'))
def __init__(self, schema, types=(), resolver=None, format_checker=None, skip_meta_validation=False): super(PandelVisitor, self).__init__( schema, types, resolver, format_checker) self._types.update({ # type(np.nan) == builtins.float! FIXME, are numpy-numbers --> # json-types OK?? "number": (numbers.Number, np.number), "integer": (int, np.integer), "boolean": (bool, np.bool_), # , np.bool8), "array": (list, tuple, np.ndarray), "object": (dict, pd.DataFrame, pd.Series) }) # Setup Draft4/3 validation # # Meta-validate schema # with original validators (and not self) # because this class inherits an empty (schema/rules) validator. # Falls back to 'Draft4' if no `$schema` exists. validator_class = jsonschema.validators.validator_for(schema) self.VALIDATORS = validator_class.VALIDATORS.copy() self.META_SCHEMA = validator_class.META_SCHEMA self.VALIDATORS.update({ 'items': PandelVisitor._rule_items, 'additionalProperties': PandelVisitor._rule_additionalProperties, 'additionalItems': PandelVisitor._rule_additionalItems, }) if validator_class == Draft3Validator: self.VALIDATORS.update({ 'properties': PandelVisitor._rule_properties_draft3, }) else: self.VALIDATORS.update({ 'properties': PandelVisitor._rule_properties_draft4, 'required': PandelVisitor._rule_required_draft4, }) self.old_scopes = [] # Cannot use ``validator_class.check_schema()`` because # need to relay my args to ``validator_class.__init__()``. # Even better use myself, that i'm fatser (kind of...). if not skip_meta_validation: for error in self.iter_errors(schema, validator_class.META_SCHEMA): raise SchemaError.create_from(error)
def is_controlled_vocabulary(validator, value, instance, schema): if not isinstance(instance, str): yield ValidationError("%r is not a string" % instance) ontology = value.get('ontology', None) if not ontology: yield SchemaError('must provide "ontology" for "vocabulary" in schema') children_of = value.get('children_of', None) is_strict = value.get('strict', True) if not term_found_in_ontology(instance, ontology, children_of): err_msg = f'value "{instance}" not found in "{ontology}" ontology' if children_of: err_msg += f' (children nodes of "{children_of}")' if is_strict: # raise a valiation error, this is the default yield ValidationError(err_msg) else: # just print out a warning msg print("Warning:", err_msg)
def check_schema(cls, schema): for error in cls(cls.META_SCHEMA).iter_errors(schema): raise SchemaError.create_from(error)
def check_schema(self, schema): from jsonschema.exceptions import SchemaError for error in default_meta_validator.iter_errors(schema): raise SchemaError.create_from(error)
def custom_validation(cls, params): if 'password' not in params and 'key' not in params: raise SchemaError('Missing password or key')
def validate_against(self, instance, schemauris=[], strict=False): """ validate the instance against each of the schemas identified by the list of schemauris. For the instance to be considered valid, it must validate against each of the named schemas. $extensionSchema properties within the instance are ignored. :argument instance: a parsed JSON document to be validated. :argument list schemauris: a list of URIs of the schemas to validate against. :return list: a list of encountered errors in the form of exceptions; otherwise, an empty list if the instance is valid against all schemas. """ if isinstance(schemauris, (str, unicode)): schemauris = [schemauris] schema = None out = [] for uri in schemauris: val = self._validators.get(uri) if not val: (urib, frag) = self._spliturifrag(uri) schema = self._schemaStore.get(urib) if not schema: try: schema = self._loader(urib) except KeyError as e: ex = MissingSchemaDocument( "Unable to find schema document for " + urib) if strict: out.append(ex) continue resolver = jsch.RefResolver(uri, schema, self._schemaStore, handlers=self._handler) if frag: try: schema = resolver.resolve_fragment(schema, frag) except RefResolutionError as ex: exc = RefResolutionError( "Unable to resolve fragment, {0} from schema, {1} ({2})" .format(frag, urib, str(ex))) out.append(exc) continue cls = jsch.validator_for(schema) # check the schema for errors scherrs = [ SchemaError.create_from(err) \ for err in cls(cls.META_SCHEMA).iter_errors(schema) ] if len(scherrs) > 0: out.extend(scherrs) continue val = cls(schema, resolver=resolver) out.extend([err for err in val.iter_errors(instance)]) self._validators[uri] = val self._schemaStore.update(val.resolver.store) return out