Пример #1
0
def openapi_spec() -> apispec.APISpec:
    """Return OpenAPI (fka Swagger) spec for API."""
    spec = apispec.APISpec(
        title="httpstan HTTP-based REST API",
        version=httpstan.__version__,
        openapi_version="2.0",
        # plugin order, MarshmallowPlugin resolves schema references created by DocPlugin
        plugins=[DocPlugin(),
                 apispec.ext.marshmallow.MarshmallowPlugin()],
    )
    spec.path(path="/v1/health", view=views.handle_health)
    spec.path(path="/v1/models", view=views.handle_create_model)
    spec.path(path="/v1/models", view=views.handle_list_models)
    spec.path(path="/v1/models/{model_id}", view=views.handle_delete_model)
    spec.path(path="/v1/models/{model_id}/params",
              view=views.handle_show_params)
    spec.path(path="/v1/models/{model_id}/log_prob",
              view=views.handle_log_prob)
    spec.path(path="/v1/models/{model_id}/log_prob_grad",
              view=views.handle_log_prob_grad)
    spec.path(path="/v1/models/{model_id}/write_array",
              view=views.handle_write_array)
    spec.path(path="/v1/models/{model_id}/transform_inits",
              view=views.handle_transform_inits)
    spec.path(path="/v1/models/{model_id}/fits", view=views.handle_create_fit)
    spec.path(path="/v1/models/{model_id}/fits/{fit_id}",
              view=views.handle_get_fit)
    spec.path(path="/v1/models/{model_id}/fits/{fit_id}",
              view=views.handle_delete_fit)
    spec.path(path="/v1/operations/{operation_id}",
              view=views.handle_get_operation)
    apispec.utils.validate_spec(spec)
    return spec
Пример #2
0
def create_app():
    app = flask.Flask(__name__)
    app.config.from_object(get_config())

    api_title = 'starter_pack'
    version = '1.0.0'

    spec = apispec.APISpec(
        title=api_title,
        version=version,
        plugins=[
            'apispec.ext.flask',
        ],
    )

    swagger_url = '/docs'

    def doc_spec():
        return json.dumps(spec.to_dict())

    blueprint = starter_pack.routes.create_blueprint_with_routes()
    blueprint.add_url_rule('/spec.json', view_func=doc_spec)
    app.register_blueprint(
        create_swagger_ui(swagger_url, api_title), url_prefix=swagger_url
    )
    app.register_blueprint(blueprint)

    print('Environment: {}'.format(app.config['ENVIRONMENT']))
    return app
Пример #3
0
def generate_schema(api, config=None):
    if not config:
        cwd = os.getcwd()
        try:
            with open(os.path.join(cwd, '.feistyrc.yaml')) as f:
                config = yaml.load(f)
        except (IOError, OSError):
            raise ValueError('Could not find .feistyrc.yaml file')

    schema = FeistyConfigSchema()
    result = schema.load(config)

    if result.errors:
        raise ValueError('Invalid Feisty config: {}'.format(result.errors))

    config = result.data

    spec = apispec.APISpec(
        config['title'],
        str(config['version']),
        openapi_version='2.0',
        plugins=(apispec.ext.marshmallow.MarshmallowPlugin(), ))

    _recurse_nodes(api._router._roots, spec)

    return spec
Пример #4
0
    def test_multi_operation_multi_reponses(self, openapi_version):
        """Should loop all operations and all responses."""
        spec = apispec.APISpec('title', 'version', openapi_version)
        plugin = ResponseReferencesPlugin()
        plugin.init_spec(spec)

        operations = {
            'get': {
                'responses': {
                    http.HTTPStatus.OK.value:
                    http.HTTPStatus.OK.name,
                    http.HTTPStatus.NO_CONTENT.value:
                    http.HTTPStatus.NO_CONTENT.name,
                }
            },
            'post': {
                'responses': {
                    http.HTTPStatus.OK.value:
                    http.HTTPStatus.OK.name,  # Ignored repeat
                    http.HTTPStatus.CREATED.value:
                    http.HTTPStatus.CREATED.name,
                }
            },
        }

        plugin.operation_helper(operations=operations)

        components = spec.to_dict()
        if openapi_version == '3.0.2':
            components = components['components']

        assert len(components['responses']) == 3  # 200, 201, 204
Пример #5
0
def make_apispec(handlers, output='data/basic-apispec.json'):
    spec = apispec.APISpec(
        title='BasicRESTSpec',
        version='1.5.6',
        info=dict(description='OpenAPI specification for the Resort server'),
        plugins=['apispec.ext.tornado'])
    for urlspec in handlers:
        spec.add_path(urlspec=urlspec)
    output_fullpath = os.path.abspath(output)
    with open(output_fullpath, 'w') as fp:
        json.dump(spec.to_dict(), fp)
Пример #6
0
def openapi_spec() -> str:
    """Return OpenAPI (fka Swagger) spec for API."""
    spec = apispec.APISpec(
        title="httpstan API", version=httpstan.__version__, plugins=["apispec.ext.marshmallow"]
    )
    spec.add_path(path="/v1/models", view=views.handle_models)
    spec.add_path(path="/v1/models/{model_id}/actions", view=views.handle_models_actions)
    spec.add_path(path="/v1/models/{model_id}/params", view=views.handle_models_params)
    spec.definition("Model", schema=views.ModelSchema)
    spec.definition("ModelsAction", schema=views.ModelsActionSchema)
    spec.definition("Param", schema=views.ParamSchema)
    return json.dumps(spec.to_dict())
Пример #7
0
    def _init_spec(self,
                   *,
                   flask_plugin=None,
                   marshmallow_plugin=None,
                   extra_plugins=None,
                   openapi_version=None,
                   **options):
        # Plugins
        self.flask_plugin = flask_plugin or FlaskPlugin()
        self.ma_plugin = marshmallow_plugin or MarshmallowPlugin()
        plugins = [self.flask_plugin, self.ma_plugin]
        plugins.extend(extra_plugins or ())

        # APISpec options
        openapi_version = self._app.config.get('OPENAPI_VERSION',
                                               openapi_version)
        if openapi_version is None:
            raise OpenAPIVersionNotSpecified(
                'The OpenAPI version must be specified, either as '
                '"OPENAPI_VERSION" app parameter or as '
                '"openapi_version" spec kwarg.')
        openapi_major_version = int(openapi_version.split('.')[0])
        if openapi_major_version < 3:
            base_path = self._app.config.get('APPLICATION_ROOT')
            options.setdefault('basePath', base_path)
            options.setdefault('produces', [
                DEFAULT_RESPONSE_CONTENT_TYPE,
            ])
            options.setdefault('consumes', [
                DEFAULT_REQUEST_BODY_CONTENT_TYPE,
            ])
        options.update(self._app.config.get('API_SPEC_OPTIONS', {}))

        # Instantiate spec
        self.spec = apispec.APISpec(
            self._app.name,
            self._app.config.get('API_VERSION', '1'),
            openapi_version=openapi_version,
            plugins=plugins,
            **options,
        )

        # Register custom fields in spec
        for args in self._fields:
            self._register_field(*args)
        # Register custom converters in spec
        for args in self._converters:
            self._register_converter(*args)
        # Register Upload field properties function
        self.ma_plugin.converter.add_attribute_function(uploadfield2properties)

        # Register OpenAPI command group
        self._app.cli.add_command(openapi_cli)
Пример #8
0
def openapi_spec() -> str:
    """Return OpenAPI (fka Swagger) spec for API."""
    spec = apispec.APISpec(
        title='httpstan API',
        version=httpstan.__version__,
        plugins=['apispec.ext.marshmallow'],
    )
    spec.add_path(path='/v1/programs', view=views.handle_programs)
    spec.add_path(path='/v1/programs/{program_id}/actions',
                  view=views.handle_programs_actions)
    spec.definition('Program', schema=views.ProgramSchema)
    spec.definition('ProgramAction', schema=views.ProgramActionSchema)
    return json.dumps(spec.to_dict())
Пример #9
0
    def _init_spec(self,
                   *,
                   flask_plugin=None,
                   marshmallow_plugin=None,
                   extra_plugins=None,
                   openapi_version=None,
                   **options):
        # Plugins
        self.flask_plugin = flask_plugin or FlaskPlugin()
        self.ma_plugin = marshmallow_plugin or MarshmallowPlugin()
        plugins = [self.flask_plugin, self.ma_plugin]
        plugins.extend(extra_plugins or ())

        # APISpec options
        openapi_version = self._app.config.get('OPENAPI_VERSION',
                                               openapi_version)
        if openapi_version is None:
            raise OpenAPIVersionNotSpecified(
                'The OpenAPI version must be specified, either as '
                '"OPENAPI_VERSION" app parameter or as '
                '"openapi_version" spec kwarg.')
        openapi_major_version = int(openapi_version.split('.')[0])
        if openapi_major_version < 3:
            base_path = self._app.config.get('APPLICATION_ROOT')
            options.setdefault('basePath', base_path)
            options.setdefault('produces', [
                'application/json',
            ])
            options.setdefault('consumes', [
                'application/json',
            ])
        options.update(self._app.config.get('API_SPEC_OPTIONS', {}))

        # Instantiate spec
        self.spec = apispec.APISpec(
            self._app.name,
            self._app.config.get('API_VERSION', '1'),
            openapi_version=openapi_version,
            plugins=plugins,
            **options,
        )

        # Register custom fields in spec
        for args in self._fields:
            self._register_field(*args)
        # Register schemas in spec
        for name, schema_cls, kwargs in self._schemas:
            self.spec.components.schema(name, schema=schema_cls, **kwargs)
        # Register custom converters in spec
        for args in self._converters:
            self._register_converter(*args)
Пример #10
0
    def __init__(self, title: str, version: str, description: str, openapi_version="3.0.0"):
        assert apispec is not None, "`apispec` must be installed to use SchemaGenerator."

        from apispec.ext.marshmallow import MarshmallowPlugin

        marshmallow_plugin = MarshmallowPlugin()
        self.spec = apispec.APISpec(
            title=title,
            version=version,
            openapi_version=openapi_version,
            info={"description": description},
            plugins=[marshmallow_plugin],
        )

        self.converter = marshmallow_plugin.converter
        self.resolver = marshmallow_plugin.resolver

        # Builtin definitions
        self.schemas = SchemaRegistry(self.spec, self.resolver)
Пример #11
0
def setup_apispec(app):
    """Setup Swagger UI.

    Args:
        app ([flask.Flask]): the application
    """

    app.config.update({
        "APISPEC_SPEC":
        apispec.APISpec(
            title="cnapps API",
            version="",
            info=dict(description="REST API of Cnapps."),
            plugins=("apispec.ext.marshmallow", ),
        ),
        # 'APISPEC_SWAGGER_UI_URL': "/%s/swagger-ui" % core.PATH,
        # 'APISPEC_SWAGGER_URL': "/%s/swagger" % core.PATH,
    })
    docs = flask_apispec.FlaskApiSpec(app)
    # PB: on a aussi l'API en defaults avec :
    # docs.register_existing_resources()
    v1_api_path = "/api/%s" % v1_core.PATH
    v1alpha_api_path = "/api/%s" % v1alpha_core.PATH
    for name, rule in app.view_functions.items():
        try:
            blueprint_name, _ = name.split(".")
            if isinstance(rule, types.FunctionType):
                paths = docs.view_converter.convert(rule, None, blueprint_name)
                LOGGER.debug("Endpoint: %s", paths[0]["path"])
                if paths[0]["path"].startswith(v1_api_path) or paths[0][
                        "path"].startswith(v1alpha_api_path):
                    LOGGER.info("Add to Swagger: %s", paths[0]["path"])
                    docs.register(rule, blueprint=blueprint_name)
                elif paths[0]["path"].startswith("/api/apis"):
                    docs.register(rule, blueprint=blueprint_name)

        except ValueError:
            pass

        except TypeError:
            pass
Пример #12
0
def create_spec() -> apispec.APISpec:
    """
    Create an `APISpec` that documents the MHS API
    :return: the `APISpec` that documents the MHS API
    """
    spec = apispec.APISpec(title='MHS API docs',
                           version='0.1',
                           openapi_version='3.0.2',
                           plugins=[
                               apispec.ext.marshmallow.MarshmallowPlugin(),
                               apispec_webframeworks.tornado.TornadoPlugin()
                           ])

    spec.components.schema("RequestBody",
                           schema=request_body_schema.RequestBodySchema)

    # The paths here should match the paths in main.py
    spec.path(urlspec=(r'/', handler.SynchronousHandler))
    spec.path(urlspec=(r'/healthcheck',
                       healthcheck_handler.HealthcheckHandler))

    return spec
Пример #13
0
    def test_api_registers_error_responses(self, openapi_version,
                                           http_status_code, http_status_name):
        """Responses should be added to spec."""
        spec = apispec.APISpec('title', 'version', openapi_version)
        plugin = ResponseReferencesPlugin()
        plugin.init_spec(spec)

        operations = {
            'get': {
                'responses': {
                    http_status_code: http_status_name,
                }
            }
        }

        plugin.operation_helper(operations=operations)

        components = spec.to_dict()
        if openapi_version == '3.0.2':
            components = components['components']

        assert len(components['responses']) == 1
        assert http_status_name in components['responses']
Пример #14
0
    def test_repeated_response(self, openapi_version):
        """Repeated response, different endpoint."""
        spec = apispec.APISpec('title', 'version', openapi_version)
        plugin = ResponseReferencesPlugin()
        plugin.init_spec(spec)

        operations = {
            'get': {
                'responses': {
                    http.HTTPStatus.OK.value: http.HTTPStatus.OK.name,
                }
            }
        }

        # operation_helper is called on each path, so this simulates
        # 2 endpoints with the same response
        plugin.operation_helper(operations=copy.deepcopy(operations))
        plugin.operation_helper(operations=copy.deepcopy(operations))

        components = spec.to_dict()
        if openapi_version == '3.0.2':
            components = components['components']

        assert len(components['responses']) == 1
Пример #15
0
def add_routes_from(module, spec):
    for _, f in vars(module).items():
        if callable(f) and hasattr(f, 'func_doc') and getattr(f, 'func_doc'):
            try:
                spec.add_path(view=f)
            except apispec.exceptions.APISpecError:
                print(
                    "Failed to add documented callable {} to swagger.".format(
                        f))


spec = apispec.APISpec(
    title='trackit.io',
    version=BUILD_VERSION,
    plugins=[
        'apispec.ext.flask',
        'apispec.ext.marshmallow',
    ],
)

ctx = app.test_request_context()
ctx.push()

from app.views.aws import account_management, forecast, usage, aws_key_schema
from app.views.aws.cost import cost, stats

add_routes_from(account_management, spec)
add_routes_from(cost, spec)
add_routes_from(stats, spec)
add_routes_from(forecast, spec)
add_routes_from(usage, spec)
Пример #16
0
import apispec
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import DocumentedBlueprint, FlaskPlugin
from flask import jsonify
from flask.views import MethodView

spec = apispec.APISpec(
    title="Swagger Petstore",
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
)

bp = DocumentedBlueprint('documented_bp', __name__, spec)


@bp.route('/')
def index():
    """
    Gist detail view.

    ---
    x-extension: metadata
    get:
        responses:
            200:
                schema:
                    $ref: '#/definitions/Gist'
    """
    return 'index'
Пример #17
0
import apispec
from apispec.exceptions import DuplicateComponentNameError
from apispec.ext.marshmallow import MarshmallowPlugin
from contextlib import suppress
from .schemas import *
from .resources import *
from inspect import isclass
from marshmallow.fields import String
from drowsy.schema import ModelResourceSchema
from drowsy.fields import NestedRelated, APIUrl
import inflection

ma_plugin = MarshmallowPlugin()

spec = apispec.APISpec(title="Swagger Docs",
                       version="0.1.1",
                       openapi_version="3.0.2",
                       plugins=[ma_plugin])


def nestedrelated2properties(self, field, **kwargs):
    """Handle NestedRelated Drowsy field.

    Only needed due to potential use of `many=True`, whereas Nested
    fields are often embedded in List fields. This is pretty hacky,
    and basically just moves around properties that `nested2properties`
    generated.

    :param MarshmallowPlugin self: This method will end up bound to a
        MarshmallowPlugin instance.
    :param field: The marshmallow field being converted.
    :return: A dict of properties to be included in our spec.
Пример #18
0
    def _init_spec(self,
                   *,
                   flask_plugin=None,
                   marshmallow_plugin=None,
                   response_plugin=None,
                   extra_plugins=None,
                   title=None,
                   version=None,
                   openapi_version=None,
                   **options):
        # Plugins
        self.flask_plugin = flask_plugin or FlaskPlugin()
        self.ma_plugin = marshmallow_plugin or MarshmallowPlugin()
        self.resp_plugin = (response_plugin
                            or ResponseReferencesPlugin(self.ERROR_SCHEMA))
        plugins = [self.flask_plugin, self.ma_plugin, self.resp_plugin]
        plugins.extend(extra_plugins or ())

        # APISpec options
        title = self._app.config.get('API_TITLE', title)
        if title is None:
            raise MissingAPIParameterError(
                'API title must be specified either as "API_TITLE" '
                'app parameter or as "title" spec kwarg.')
        version = self._app.config.get('API_VERSION', version)
        if version is None:
            raise MissingAPIParameterError(
                'API version must be specified either as "API_VERSION" '
                'app parameter or as "version" spec kwarg.')
        openapi_version = self._app.config.get('OPENAPI_VERSION',
                                               openapi_version)
        if openapi_version is None:
            raise MissingAPIParameterError(
                'OpenAPI version must be specified either as "OPENAPI_VERSION '
                'app parameter or as "openapi_version" spec kwarg.')
        openapi_major_version = int(openapi_version.split('.')[0])
        if openapi_major_version < 3:
            options.setdefault('produces', [
                DEFAULT_RESPONSE_CONTENT_TYPE,
            ])
            options.setdefault('consumes', [
                DEFAULT_REQUEST_BODY_CONTENT_TYPE,
            ])
        options.update(self._app.config.get('API_SPEC_OPTIONS', {}))

        # Instantiate spec
        self.spec = apispec.APISpec(
            title,
            version,
            openapi_version,
            plugins,
            **options,
        )

        # Register custom fields in spec
        for args in self._fields:
            self._register_field(*args)
        # Register custom converters in spec
        for args in self._converters:
            self._register_converter(*args)
        # Register Upload field properties function
        self.ma_plugin.converter.add_attribute_function(uploadfield2properties)

        # Register OpenAPI command group
        self._app.cli.add_command(openapi_cli)
Пример #19
0
        os.getcwd(), 'config',
        os.getenv('APPLICATION_ENV', 'development').lower() + '.config'))

# Create an API doc store for Swagger
version_file_path = 'version.json'
if isfile(version_file_path):
    version_details = json.loads(open(version_file_path).read())
    version = 'Build: {0}, Commit: {1}'.format(version_details['build_no'],
                                               version_details['commit'])
else:
    version = 'No {} file found.'.format(version_file_path)

app.api_doc = apispec.APISpec(
    title='Range Planning Tool',
    version=version,
    description='Sainsburys range planner project.',
    plugins=[
        'apispec.ext.flask',
        'apispec.ext.marshmallow',
    ],
)

from api import api as api_blueprint

app.register_blueprint(api_blueprint, url_prefix='/api')

for view_name in app.view_functions.keys():
    if not view_name.startswith('_') and view_name not in ['static']:
        view_fn = app.view_functions[view_name]
        app.api_doc.add_path(view=view_fn)
Пример #20
0
import apispec
import apispec.ext.marshmallow
import apispec_webframeworks.flask

from ..api import _examples as ex
from ..config import Config

spec = apispec.APISpec(
    title=Config.APPLICATION_NAME,
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[
        apispec_webframeworks.flask.FlaskPlugin(),
        apispec.ext.marshmallow.MarshmallowPlugin(),
    ],
    servers=[{
        "url": "http://localhost:5000/"
    }],
)

example2 = {
    "code": 400,
    "description": {
        "extra": ["Unknown field."]
    },
    "name": "Bad Request",
}


def _error(error, example, schema=None):
    content = {"example": example}