Source code for flask_restplus.schemas

# -*- coding: utf-8 -*-
'''
This module give access to OpenAPI specifications schemas
and allows to validate specs against them.

.. versionadded:: 0.12.1
'''
from __future__ import unicode_literals

import io
import json
import pkg_resources

from collections import Mapping

from jsonschema import Draft4Validator

from flask_restplus import errors


[docs]class SchemaValidationError(errors.ValidationError): ''' Raised when specification is not valid .. versionadded:: 0.12.1 ''' def __init__(self, msg, errors=None): super(SchemaValidationError, self).__init__(msg) self.errors = errors def __str__(self): msg = [self.msg] for error in sorted(self.errors, key=lambda e: e.path): path = '.'.join(error.path) msg.append('- {}: {}'.format(path, error.message)) for suberror in sorted(error.context, key=lambda e: e.schema_path): path = '.'.join(suberror.schema_path) msg.append(' - {}: {}'.format(path, suberror.message)) return '\n'.join(msg) __unicode__ = __str__
[docs]class LazySchema(Mapping): ''' A thin wrapper around schema file lazy loading the data on first access :param filename str: The package relative json schema filename :param validator: The jsonschema validator class version .. versionadded:: 0.12.1 ''' def __init__(self, filename, validator=Draft4Validator): super(LazySchema, self).__init__() self.filename = filename self._schema = None self._validator = validator def _load(self): if not self._schema: filename = pkg_resources.resource_filename(__name__, self.filename) with io.open(filename) as infile: self._schema = json.load(infile) def __getitem__(self, key): self._load() return self._schema.__getitem__(key) def __iter__(self): self._load() return self._schema.__iter__() def __len__(self): self._load() return self._schema.__len__() @property def validator(self): '''The jsonschema validator to validate against''' return self._validator(self)
#: OpenAPI 2.0 specification schema OAS_20 = LazySchema('oas-2.0.json') #: Map supported OpenAPI versions to their JSON schema VERSIONS = { '2.0': OAS_20, }
[docs]def validate(data): ''' Validate an OpenAPI specification. Supported OpenAPI versions: 2.0 :param data dict: The specification to validate :returns boolean: True if the specification is valid :raises SchemaValidationError: when the specification is invalid :raises flask_restplus.errors.SpecsError: when it's not possible to determinate the schema to validate against .. versionadded:: 0.12.1 ''' if 'swagger' not in data: raise errors.SpecsError('Unable to determinate OpenAPI schema version') version = data['swagger'] if version not in VERSIONS: raise errors.SpecsError('Unknown OpenAPI schema version "{}"'.format(version)) validator = VERSIONS[version].validator validation_errors = list(validator.iter_errors(data)) if validation_errors: raise SchemaValidationError('OpenAPI {} validation failed'.format(version), errors=validation_errors) return True