def test_it_delegates_to_a_ref_resolver(self): ref, schema = "someCoolRef", {"type": "integer"} resolver = validators.RefResolver("", {}, store={ref: schema}) validator = self.Validator({"$ref": ref}, resolver=resolver) with self.assertRaises(ValidationError): validator.validate(None)
def _make_resolver(url_mapping): handlers = {} schema_loader = _make_schema_loader(url_mapping) def get_schema(url): return schema_loader(url)[0] for x in ['http', 'https', 'file', 'tag', 'asdf']: handlers[x] = get_schema # Supplying our own implementation of urljoin_cache # allows asdf:// URIs to be resolved correctly. urljoin_cache = lru_cache(1024)(patched_urllib_parse.urljoin) # We set cache_remote=False here because we do the caching of # remote schemas here in `load_schema`, so we don't need # jsonschema to do it on our behalf. Setting it to `True` # counterintuitively makes things slower. return mvalidators.RefResolver( '', {}, cache_remote=False, handlers=handlers, urljoin_cache=urljoin_cache, )
def create_spec(spec_dict: dict) -> models.Spec: """Create and return the OpenAPI v3 Spec Model""" spec_resolver = jsonschema_validators.RefResolver( '', spec_dict, handlers=openapi_spec_validator.default_handlers) spec_factory = factories.SpecFactory( spec_resolver, config={'validate_spec': False}) return spec_factory.create(spec_dict, spec_url='')
def setUp(self): self.referrer = {} self.store = {self.stored_uri: self.stored_schema} self.resolver = validators.RefResolver( self.base_uri, self.referrer, self.store, )
def scrub_index_data(index_data: dict, bundle_id: str) -> list: cache = S3UrlCache() def request_json(url): return json.loads(cache.resolve(url).decode("utf-8")) resolver = validators.RefResolver(referrer='', base_uri='', handlers={ 'http': request_json, 'https': request_json }) extra_fields = [] extra_documents = [] for document in index_data.keys(): for doc_list_ind, document_content in enumerate(index_data[document]): schema_info = SchemaInfo.from_json(document_content) if schema_info is not None: try: schema = request_json(schema_info.url) except Exception as ex: extra_documents.append(document) logger.warning( f"Unable to retrieve JSON schema information from {document} in bundle {bundle_id} " f"because retrieving {schema_info.url} caused exception: {ex}." ) else: for error in DSS_Draft4Validator( schema, resolver=resolver).iter_errors(document_content): if error.validator == 'additionalProperties': path = [document, doc_list_ind, *error.path] # Example error message: "Additional properties are not allowed ('extra_lst', 'extra_top' # were unexpected)" or "'extra', does not match any of the regexes: '^characteristics_.*$'" fields_to_remove = (path, [ field for field in _utils.find_additional_properties( error.instance, error.schema) ]) extra_fields.append(fields_to_remove) else: logger.warning( f"Unable to retrieve JSON schema information from {document} in bundle {bundle_id}." ) extra_documents.append(document) if extra_documents: extra_fields.append(([], extra_documents)) removed_fields = [] for path, fields in extra_fields: remove_json_fields(index_data, path, fields) removed_fields.extend( ['.'.join((*[str(p) for p in path], field)) for field in fields]) if removed_fields: logger.info( f"In {bundle_id}, unexpected additional fields have been removed from the data" f" to be indexed. Removed {removed_fields}.") return removed_fields
def test_cache_remote_off(self): ref = "foo://bar" foo_handler = mock.Mock() resolver = validators.RefResolver( "", {}, cache_remote=False, handlers={"foo": foo_handler}, ) with resolver.resolving(ref): pass self.assertEqual(foo_handler.call_count, 1)
def test_if_you_give_it_junk_you_get_a_resolution_error(self): ref = "foo://bar" foo_handler = mock.Mock(side_effect=ValueError("Oh no! What's this?")) resolver = validators.RefResolver( "", {}, handlers={"foo": foo_handler}, ) with self.assertRaises(validators.RefResolutionError) as err: with resolver.resolving(ref): pass self.assertEqual(str(err.exception), "Oh no! What's this?")
def test_it_delegates_to_a_ref_resolver(self): resolver = validators.RefResolver("", {}) schema = {"$ref": mock.Mock()} with mock.patch.object(resolver, "resolve") as resolve: resolve.return_value = "url", {"type": "integer"} with self.assertRaises(ValidationError): self.validator_class(schema, resolver=resolver).validate(None) resolve.assert_called_once_with(schema["$ref"])
def test_custom_uri_scheme_handlers(self): def handler(url): self.assertEqual(url, ref) return schema schema = {"foo": "bar"} ref = "foo://bar" resolver = validators.RefResolver("", {}, handlers={"foo": handler}) with resolver.resolving(ref) as resolved: self.assertEqual(resolved, schema)
def test_custom_uri_scheme_handlers(self): schema = {"foo": "bar"} ref = "foo://bar" foo_handler = mock.Mock(return_value=schema) resolver = validators.RefResolver( "", {}, handlers={"foo": foo_handler}, ) with resolver.resolving(ref) as resolved: self.assertEqual(resolved, schema) foo_handler.assert_called_once_with(ref)
def test_cache_remote_on(self): ref = "foo://bar" foo_handler = mock.Mock() resolver = validators.RefResolver( "", {}, cache_remote=True, handlers={"foo": foo_handler}, ) with resolver.resolving(ref): pass with resolver.resolving(ref): pass foo_handler.assert_called_once_with(ref)
def test_if_you_give_it_junk_you_get_a_resolution_error(self): error = ValueError("Oh no! What's this?") def handler(url): raise error ref = "foo://bar" resolver = validators.RefResolver("", {}, handlers={"foo": handler}) with self.assertRaises(validators.RefResolutionError) as err: with resolver.resolving(ref): self.fail("Shouldn't get this far!") # pragma: no cover self.assertEqual(err.exception, validators.RefResolutionError(error))
def _make_resolver(url_mapping): handlers = {} schema_loader = _make_schema_loader(url_mapping) for x in ['http', 'https', 'file']: handlers[x] = schema_loader # We set cache_remote=False here because we do the caching of # remote schemas here in `load_schema`, so we don't need # jsonschema to do it on our behalf. Setting it to `True` # counterintuitively makes things slower. return validators.RefResolver('', {}, cache_remote=False, handlers=handlers)
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 test_cache_remote_off(self): response = [object()] def handler(url): try: return response.pop() except IndexError: # pragma: no cover self.fail("Handler called twice!") ref = "foo://bar" resolver = validators.RefResolver( "", {}, cache_remote=False, handlers={"foo": handler}, ) with resolver.resolving(ref): pass
def test_cache_remote_on(self): response = [object()] def handler(url): try: return response.pop() except IndexError: # pragma: no cover self.fail("Response must not have been cached!") ref = "foo://bar" resolver = validators.RefResolver( "", {}, cache_remote=True, handlers={"foo": handler}, ) with resolver.resolving(ref): pass with resolver.resolving(ref): pass
def validate(instance, schema, resolver=None, *args, **kwargs): """ Validate the given instance against the given schema using the YAML schema extensions to JSON schema. The arguments are the same as to `jsonschema.validate`. """ create_validator() handlers = {} for x in ['http', 'https', 'file']: handlers[x] = _make_schema_loader(resolver) kwargs['resolver'] = validators.RefResolver(schema.get('id', ''), schema, cache_remote=False, handlers=handlers) # We don't just call validators.validate() directly here, because # that validates the schema itself, wasting a lot of time (at the # time of this writing, it was half of the runtime of the unit # test suite!!!). Instead, we assume that the schemas are valid # through the running of the unit tests, not at run time. cls = validators.validator_for(schema) cls(schema, *args, **kwargs).validate(instance)
def test_helpful_error_message_on_failed_pop_scope(self): resolver = validators.RefResolver("", {}) resolver.pop_scope() with self.assertRaises(validators.RefResolutionError) as exc: resolver.pop_scope() self.assertIn("Failed to pop the scope", str(exc.exception))
def test_False_is_not_a_schema_even_if_you_forget_to_check(self): resolver = validators.RefResolver("", {}) with self.assertRaises(TypeError): self.Validator(False, resolver=resolver).validate(12)
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