def init_app(self, app): self.app = app self.spec = self.app.config.get('APISPEC_SPEC') or \ make_apispec(self.app.config.get('APISPEC_TITLE', 'flask-apispec'), self.app.config.get('APISPEC_VERSION', 'v1')) self.add_swagger_routes() self.resource_converter = ResourceConverter(self.app, spec=self.spec) self.view_converter = ViewConverter(app=self.app, spec=self.spec) for deferred in self._deferred: deferred()
def test_error_if_spec_does_not_have_marshmallow_plugin(app): bad_spec = APISpec( title='title', version='v1', plugins=[], # oh no! no MarshmallowPlugin ) with pytest.raises(RuntimeError): ViewConverter(app=app, spec=bad_spec) with pytest.raises(RuntimeError): ResourceConverter(app=app, spec=bad_spec)
def init_app(self): """Override base init_app method.""" self.view_converter = ViewConverter(self.app) self.resource_converter = ResourceConverter(self.app) self.spec = APISpec(title=self.title, version=self.version, info={'description': self.top_level_description}, plugins=['apispec.ext.marshmallow']) self.add_swagger_routes() for deferred in self._deferred: deferred()
def init_app(self, **kwargs): """ Override base init_app method. :param kwargs: args """ self.spec = APISpec(title=self.title, version=self.version, info={'description': self.top_level_description}, plugins=[MarshmallowPlugin()], openapi_version='2.0') self.resource_converter = ResourceConverter(self.app, self.spec) self.view_converter = ViewConverter(self.app, self.spec) self.add_swagger_routes() for deferred in self._deferred: deferred()
class FlaskApiSpec(object): """Flask-apispec extension. Usage: .. code-block:: python app = Flask(__name__) app.config.update({ 'APISPEC_SPEC': APISpec( title='pets', version='v1', openapi_version='2.0', plugins=[MarshmallowPlugin()], ), 'APISPEC_SWAGGER_URL': '/swagger/', }) docs = FlaskApiSpec(app) @app.route('/pet/<pet_id>') def get_pet(pet_id): return Pet.query.filter(Pet.id == pet_id).one() docs.register(get_pet) :param Flask app: App associated with API documentation :param APISpec spec: apispec specification associated with API documentation """ def __init__(self, app=None, static_folder='./static', template_folder='./templates', static_url_path='/flask-apispec/static'): self._deferred = [] self.app = app self.view_converter = None self.resource_converter = None self.spec = None self.static_folder = static_folder self.template_folder = template_folder self.static_url_path = static_url_path if app: self.init_app(app) def init_app(self, app): self.app = app self.spec = self.app.config.get('APISPEC_SPEC') or \ make_apispec(self.app.config.get('APISPEC_TITLE', 'flask-apispec'), self.app.config.get('APISPEC_VERSION', 'v1'), self.app.config.get('APISPEC_OAS_VERSION', '2.0')) self.add_swagger_routes() self.resource_converter = ResourceConverter(self.app, spec=self.spec) self.view_converter = ViewConverter(app=self.app, spec=self.spec) for deferred in self._deferred: deferred() def _defer(self, callable, *args, **kwargs): bound = functools.partial(callable, *args, **kwargs) self._deferred.append(bound) if self.app: bound() def add_swagger_routes(self): blueprint = flask.Blueprint( 'flask-apispec', __name__, static_folder=self.static_folder, template_folder=self.template_folder, static_url_path=self.static_url_path, ) json_url = self.app.config.get('APISPEC_SWAGGER_URL', '/swagger/') if json_url: blueprint.add_url_rule(json_url, 'swagger-json', self.swagger_json) ui_url = self.app.config.get('APISPEC_SWAGGER_UI_URL', '/swagger-ui/') if ui_url: blueprint.add_url_rule(ui_url, 'swagger-ui', self.swagger_ui) self.app.register_blueprint(blueprint) def swagger_json(self): return flask.jsonify(self.spec.to_dict()) def swagger_ui(self): return flask.render_template('swagger-ui.html') def register_existing_resources(self): for name, rule in self.app.view_functions.items(): try: blueprint_name, _ = name.split('.') except ValueError: blueprint_name = None try: self.register(rule, blueprint=blueprint_name) except TypeError: pass def register(self, target, endpoint=None, blueprint=None, resource_class_args=None, resource_class_kwargs=None, custom_path=None): """Register a view. :param custom_path: (optional) Override the path property for the endpoint :param target: view function or view class. :param endpoint: (optional) endpoint name. :param blueprint: (optional) blueprint name. :param tuple resource_class_args: (optional) args to be forwarded to the view class constructor. :param dict resource_class_kwargs: (optional) kwargs to be forwarded to the view class constructor. """ self._defer(self._register, target, endpoint, blueprint, resource_class_args, resource_class_kwargs, custom_path) def _register(self, target, endpoint=None, blueprint=None, resource_class_args=None, resource_class_kwargs=None, custom_path=None): """Register a view. :param target: view function or view class. :param endpoint: (optional) endpoint name. :param blueprint: (optional) blueprint name. :param tuple resource_class_args: (optional) args to be forwarded to the view class constructor. :param dict resource_class_kwargs: (optional) kwargs to be forwarded to the view class constructor. """ if isinstance(target, types.FunctionType): paths = self.view_converter.convert(target, endpoint, blueprint) elif isinstance(target, ResourceMeta): paths = self.resource_converter.convert( target, endpoint, blueprint, resource_class_args=resource_class_args, resource_class_kwargs=resource_class_kwargs, ) else: raise TypeError() if custom_path and len(paths) == 1: path = paths[0] path['path'] = rule_path_to_path(custom_path) self.spec.path(**path) else: for path in paths: self.spec.path(**path)
def path(self, app, spec, function_view): converter = ViewConverter(app) paths = converter.convert(function_view) for path in paths: spec.add_path(**path) return spec._paths['/bands/{band_id}/']
def __init__(self, app): self.app = app self.view_converter = ViewConverter(self.app) self.resource_converter = ResourceConverter(self.app) self.spec = self.app.config.get('APISPEC_SPEC') or make_apispec() self.add_routes()
class FlaskApiSpec(object): """Flask-apispec extension. Usage: .. code-block:: python app = Flask(__name__) app.config.update({ 'APISPEC_SPEC': APISpec( title='pets', version='v1', plugins=['apispec.ext.marshmallow'], ), 'APISPEC_SWAGGER_URL': '/swagger/', }) docs = FlaskApiSpec(app) @app.route('/pet/<pet_id>') def get_pet(pet_id): return Pet.query.filter(Pet.id == pet_id).one() docs.register(get_pet) :param Flask app: App associated with API documentation :param APISpec spec: apispec specification associated with API documentation """ def __init__(self, app): self.app = app self.view_converter = ViewConverter(self.app) self.resource_converter = ResourceConverter(self.app) self.spec = self.app.config.get('APISPEC_SPEC') or make_apispec() self.add_routes() def add_routes(self): blueprint = flask.Blueprint( 'flask-apispec', __name__, static_folder='./static', template_folder='./templates', static_url_path='/flask-apispec/static', ) json_url = self.app.config.get('APISPEC_SWAGGER_URL', '/swagger/') if json_url: blueprint.add_url_rule(json_url, 'swagger-json', self.swagger_json) ui_url = self.app.config.get('APISPEC_SWAGGER_UI_URL', '/swagger-ui/') if ui_url: blueprint.add_url_rule(ui_url, 'swagger-ui', self.swagger_ui) self.app.register_blueprint(blueprint) def swagger_json(self): return flask.jsonify(self.spec.to_dict()) def swagger_ui(self): return flask.render_template('swagger-ui.html') def register(self, target, endpoint=None, blueprint=None, resource_class_args=None, resource_class_kwargs=None): """Register a view. :param target: view function or view class. :param endpoint: (optional) endpoint name. :param blueprint: (optional) blueprint name. :param tuple resource_class_args: (optional) args to be forwarded to the view class constructor. :param dict resource_class_kwargs: (optional) kwargs to be forwarded to the view class constructor. """ if isinstance(target, types.FunctionType): paths = self.view_converter.convert(target, endpoint, blueprint) elif isinstance(target, ResourceMeta): paths = self.resource_converter.convert( target, endpoint, blueprint, resource_class_args=resource_class_args, resource_class_kwargs=resource_class_kwargs, ) else: raise TypeError() for path in paths: self.spec.add_path(**path)
def path(self, app, spec_oapi3, function_view): converter = ViewConverter(app=app, spec=spec_oapi3) paths = converter.convert(function_view) for path in paths: spec_oapi3.path(**path) return spec_oapi3._paths['/bands/{band_id}/']