Exemplo n.º 1
0
def test_definition_autogeneration(app, routes):
    spec = APISpec(
        title='test api',
        version='0.1.0',
        plugins=('apispec.ext.marshmallow', 'flask_resty.spec'))

    spec.add_path(view=routes['fooList'])

    assert 'FooSchema' in spec.to_dict()['definitions']
Exemplo n.º 2
0
def test_tagging(app, routes):
    spec = APISpec(
        title='test api',
        version='0.1.0',
        plugins=('apispec.ext.marshmallow', 'flask_resty.spec'))

    spec.add_path(view=routes['fooList'])

    assert 'FooSchema' in spec.to_dict()['paths']['/foos']['get']['tags']
Exemplo n.º 3
0
def api_spec(request):
    spec = APISpec(
        title='Some API',
        version='1.0.0',
        openapi_version='2.0',
        plugins=[
            MarshmallowPlugin()
        ],
    )

    # inspect the `foo_route` and generate operations from docstring
    add_pyramid_paths(spec, 'api_object', request=request)
    add_pyramid_paths(spec, 'api_object_relation', request=request)

    return spec.to_dict()
Exemplo n.º 4
0
def spec(app, schemas, routes):
    spec = APISpec(
        title='test api',
        version='0.1.0',
        plugins=('apispec.ext.marshmallow', 'flask_resty.spec'))

    spec.definition('Foo', schema=schemas['foo'])

    spec.add_path(view=routes['fooList'])
    spec.add_path(view=routes['foo'])
    spec.add_path(view=routes['bar'])

    return spec.to_dict()
Exemplo n.º 5
0
    def get_specification(self):
        spec = APISpec(
            title=self.__class__.__name__,
            version='1.0.0',
            plugins=(
                'apispec.ext.flask',
                'apispec.ext.marshmallow',
            ),
        )

        class PetSchema(Schema):
            id = fields.Int()
            name = fields.Str()

        app = Flask(__name__)

        @app.route('/random')
        def random_pet():
            """A cute furry animal endpoint.
            ---
            get:
                description: Get a random pet
                responses:
                    200:
                        description: A pet to be returned
                        schema: PetSchema
            """
            return jsonify({})

        # Register entities and paths
        spec.definition('Pet', schema=PetSchema)
        with app.test_request_context():
            spec.add_path(view=random_pet)

        return json.dumps(spec.to_dict(), indent=4)
Exemplo n.º 6
0
    def get_specification(self):
        spec = APISpec(
            title=self.__class__.__name__,
            version='1.0.0',
            plugins=(
                'apispec.ext.flask',
                'apispec.ext.marshmallow',
            ),
        )

        class PetParameter(Schema):
            pet_id = fields.Int()

        class PetSchema(Schema):
            id = fields.Int()
            name = fields.Str()

        app = Flask(__name__)

        @app.route('/pets/<int:pet_id>')
        def get_pet(pet_id):
            """A cute furry animal endpoint.
            ---
            get:
                description: Get a random pet
                parameters:
                    - in: path
                      schema: PetParameter
                responses:
                    200:
                        description: A pet to be returned
                        schema: PetSchema
            """
            return jsonify({})

        # Register entities and paths
        spec.definition('Pet', schema=PetSchema)
        spec.definition('PetParameter', schema=PetParameter, required=True)
        with app.test_request_context():
            spec.add_path(view=get_pet)

        specification_as_string = json.dumps(spec.to_dict(), indent=4)

        # Kludge! I was unable to do this via `apispec`
        specification_as_string = specification_as_string.replace('"required": false,',
                                                                  '"required": true,')

        return specification_as_string
Exemplo n.º 7
0
def generate_specs(module_name):
    module = import_service_module(module_name)
    service_name = ''.split('.')[-1]

    ctx = module.app.test_request_context()
    ctx.push()
    spec = APISpec(
        title=service_name,
        version='1.0.0',
        plugins=('apispec.ext.marshmallow', 'flask_resty.spec'))

    schemas = get_subclasses(module.schemas, Schema)
    for schema in schemas:
        spec.definition(prettify_schema_name(schema), schema=schema)

    for view in get_subclasses(module.views, ApiView):
        try:
            spec.add_path(view=view, tag=True)
        except KeyError:
            pass  # means that the view is not registered. move along

    return json.dumps(spec.to_dict(), indent=2)
Exemplo n.º 8
0
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from marshmallow import Schema, fields, validate
from utils import make_parameter, make_request_body, make_response

specification = APISpec(
    title="Orders API",
    version="1.0.0",
    openapi_version="3.0.3",
    plugins=[MarshmallowPlugin()],
    **{
        "info": {"description": "API that allows you to manage orders for CoffeeMesh"},
        "servers": [
            {"url": "https://coffeemesh.com", "description": "main production server"},
            {
                "url": "https://coffeemesh-staging.com",
                "description": "staging server for testing purposes only",
            },
        ],
    }
)


class OrderItem(Schema):
    product = fields.String(required=True)
    size = fields.String(
        required=True, validate=validate.OneOf(["small", "medium", "big"])
    )
    quantity = fields.Integer(default=1, validate=validate.Range(1, min_inclusive=True))

Exemplo n.º 9
0
class DefaultConfig(object):
    SERVICE_NAME = os.getenv("SERVICE_NAME", "Cornflow")
    SECRET_KEY = os.getenv("SECRET_KEY")
    SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL",
                                        "sqlite:///cornflow.db")
    AIRFLOW_URL = os.getenv("AIRFLOW_URL")
    AIRFLOW_USER = os.getenv("AIRFLOW_USER")
    AIRFLOW_PWD = os.getenv("AIRFLOW_PWD")
    AUTH_TYPE = int(os.getenv("AUTH_TYPE", AUTH_DB))
    DEFAULT_ROLE = int(os.getenv("DEFAULT_ROLE", PLANNER_ROLE))
    CORS_ORIGINS = os.getenv("CORS_ORIGINS", "*")
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    DEBUG = True
    TESTING = True
    LOG_LEVEL = int(os.getenv("LOG_LEVEL", 30))
    SIGNUP_ACTIVATED = int(os.getenv("SIGNUP_ACTIVATED", 1))

    # Open deployment (all dags accessible to all users)
    OPEN_DEPLOYMENT = os.getenv("OPEN_DEPLOYMENT", 1)

    # Planner users can access objects of other users (1) or not(0).
    USER_ACCESS_ALL_OBJECTS = os.getenv("USER_ACCESS_ALL_OBJECTS", 0)

    # LDAP configuration
    LDAP_HOST = os.getenv("LDAP_HOST", "ldap://openldap:389")
    LDAP_BIND_DN = os.getenv("LDAP_BIND_DN", "cn=admin,dc=example,dc=org")
    LDAP_BIND_PASSWORD = os.getenv("LDAP_BIND_PASSWORD", "admin")
    LDAP_USERNAME_ATTRIBUTE = os.getenv("LDAP_USERNAME_ATTRIBUTE", "cn")
    LDAP_USER_BASE = os.getenv("LDAP_USER_BASE", "ou=users,dc=example,dc=org")
    LDAP_EMAIL_ATTRIBUTE = os.getenv("LDAP_EMAIL_ATTRIBUTE", "mail")
    LDAP_USER_OBJECT_CLASS = os.getenv("LDAP_USER_OBJECT_CLASS",
                                       "inetOrgPerson")

    LDAP_GROUP_OBJECT_CLASS = os.getenv("LDAP_GROUP_OBJECT_CLASS",
                                        "posixGroup")
    LDAP_GROUP_ATTRIBUTE = os.getenv("LDAP_GROUP_ATTRIBUTE", "cn")
    LDAP_GROUP_BASE = os.getenv("LDAP_GROUP_BASE",
                                "ou=groups,dc=example,dc=org")
    LDAP_GROUP_TO_ROLE_SERVICE = os.getenv("LDAP_GROUP_TO_ROLE_SERVICE",
                                           "service")
    LDAP_GROUP_TO_ROLE_ADMIN = os.getenv("LDAP_GROUP_TO_ROLE_ADMIN",
                                         "administrators")
    LDAP_GROUP_TO_ROLE_VIEWER = os.getenv("LDAP_GROUP_TO_ROLE_VIEWER",
                                          "viewers")
    LDAP_GROUP_TO_ROLE_PLANNER = os.getenv("LDAP_GROUP_TO_ROLE_PLANNER",
                                           "planners")

    LDAP_PROTOCOL_VERSION = int(os.getenv("LDAP_PROTOCOL_VERSION", 3))
    LDAP_USE_TLS = os.getenv("LDAP_USE_TLS", "False")

    # OpenID login -> Default Azure
    OID_PROVIDER = os.getenv("OID_PROVIDER", 0)
    OID_CLIENT_ID = os.getenv("OID_CLIENT_ID")
    OID_TENANT_ID = os.getenv("OID_TENANT_ID")
    OID_ISSUER = os.getenv("OID_ISSUER")

    # APISPEC:
    APISPEC_SPEC = APISpec(
        title="Cornflow API docs",
        version="v1",
        plugins=[MarshmallowPlugin()],
        openapi_version="2.0.0",
    )
    APISPEC_SWAGGER_URL = "/swagger/"
    APISPEC_SWAGGER_UI_URL = "/swagger-ui/"

    # compress config
    COMPRESS_REGISTER = False

    # Email server
    SERVICE_EMAIL_ADDRESS = os.getenv("SERVICE_EMAIL_ADDRESS", None)
    SERVICE_EMAIL_PASSWORD = os.getenv("SERVICE_EMAIL_PASSWORD", None)
    SERVICE_EMAIL_SERVER = os.getenv("SERVICE_EMAIL_SERVER", None)
    SERVICE_EMAIL_PORT = os.getenv("SERVICE_EMAIL_PORT", None)
Exemplo n.º 10
0
def test_openapi_tools_validate_v2():
    ma_plugin = MarshmallowPlugin()
    spec = APISpec(
        title='Pets',
        version='0.1',
        plugins=(ma_plugin, ),
        openapi_version='2.0',
    )
    openapi = ma_plugin.openapi

    spec.definition('Category', schema=CategorySchema)
    spec.definition('Pet',
                    schema=PetSchema,
                    extra_fields={'discriminator': 'name'})

    spec.add_path(
        view=None,
        path='/category/{category_id}',
        operations={
            'get': {
                'parameters': [
                    {
                        'name': 'q',
                        'in': 'query',
                        'type': 'string'
                    },
                    {
                        'name': 'category_id',
                        'in': 'path',
                        'required': True,
                        'type': 'string'
                    },
                    openapi.field2parameter(
                        field=fields.List(
                            fields.Str(),
                            validate=validate.OneOf(['freddie', 'roger']),
                            location='querystring',
                        ),
                        name='body',
                        use_refs=False,
                    ),
                ] + openapi.schema2parameters(PageSchema, default_in='query'),
                'responses': {
                    200: {
                        'schema': PetSchema,
                        'description': 'A pet',
                    },
                },
            },
            'post': {
                'parameters': ([{
                    'name': 'category_id',
                    'in': 'path',
                    'required': True,
                    'type': 'string'
                }] + openapi.schema2parameters(CategorySchema,
                                               default_in='body')),
                'responses': {
                    201: {
                        'schema': PetSchema,
                        'description': 'A pet',
                    },
                },
            },
        },
    )
    try:
        utils.validate_spec(spec)
    except exceptions.OpenAPIError as error:
        pytest.fail(str(error))
Exemplo n.º 11
0
class AiohttpApiSpec:
    def __init__(self,
                 url="/api/docs/swagger.json",
                 app=None,
                 request_data_name="data",
                 swagger_path=None,
                 static_path='/static/swagger',
                 error_callback=None,
                 in_place=False,
                 prefix='',
                 schema_name_resolver=resolver,
                 **kwargs):

        self.plugin = MarshmallowPlugin(
            schema_name_resolver=schema_name_resolver)
        self.spec = APISpec(plugins=(self.plugin, ),
                            openapi_version="2.0",
                            **kwargs)

        self.url = url
        self.swagger_path = swagger_path
        self.static_path = static_path
        self._registered = False
        self._request_data_name = request_data_name
        self.error_callback = error_callback
        self.prefix = prefix
        if app is not None:
            self.register(app, in_place)

    def swagger_dict(self):
        """ Returns swagger spec representation in JSON format """
        return self.spec.to_dict()

    def register(self, app: web.Application, in_place: bool = False):
        """ Creates spec based on registered app routes and registers needed view """
        if self._registered is True:
            return None

        app["_apispec_request_data_name"] = self._request_data_name

        if self.error_callback:
            parser.error_callback = self.error_callback
        app["_apispec_parser"] = parser

        if in_place:
            self._register(app)
        else:

            async def doc_routes(app_):
                self._register(app_)

            app.on_startup.append(doc_routes)

        self._registered = True

        if self.url is not None:

            async def swagger_handler(request):
                return web.json_response(request.app["swagger_dict"])

            app.router.add_route("GET",
                                 self.url,
                                 swagger_handler,
                                 name="swagger.spec")

            if self.swagger_path is not None:
                self._add_swagger_web_page(app, self.static_path,
                                           self.swagger_path)

    def _add_swagger_web_page(self, app: web.Application, static_path: str,
                              view_path: str):
        static_files = Path(__file__).parent / "static"
        app.router.add_static(static_path, static_files)

        with open(str(static_files / "index.html")) as swg_tmp:
            tmp = Template(swg_tmp.read()).render(path=self.url,
                                                  static=static_path)

        async def swagger_view(_):
            return web.Response(text=tmp, content_type="text/html")

        app.router.add_route("GET",
                             view_path,
                             swagger_view,
                             name="swagger.docs")

    def _register(self, app: web.Application):
        for route in app.router.routes():
            if issubclass_py37fix(route.handler,
                                  web.View) and route.method == METH_ANY:
                for attr in dir(route.handler):
                    if attr.upper() in METH_ALL:
                        view = getattr(route.handler, attr)
                        method = attr
                        self._register_route(route, method, view)
            else:
                method = route.method.lower()
                view = route.handler
                self._register_route(route, method, view)
        app["swagger_dict"] = self.swagger_dict()

    def _register_route(self, route: web.AbstractRoute, method: str,
                        view: _AiohttpView):

        if not hasattr(view, "__apispec__"):
            return None

        url_path = get_path(route)
        if not url_path:
            return None

        self._update_paths(view.__apispec__, method, self.prefix + url_path)

    def _update_paths(self, data: dict, method: str, url_path: str):
        if method not in VALID_METHODS_OPENAPI_V2:
            return None
        for schema in data.pop("schemas", []):
            parameters = self.plugin.converter.schema2parameters(
                schema["schema"], **schema["options"])
            data["parameters"].extend(parameters)

        existing = [p["name"] for p in data["parameters"] if p["in"] == "path"]
        data["parameters"].extend({
            "in": "path",
            "name": path_key,
            "required": True,
            "type": "string"
        } for path_key in get_path_keys(url_path) if path_key not in existing)

        if "responses" in data:
            responses = {}
            for code, actual_params in data["responses"].items():
                if "schema" in actual_params:
                    raw_parameters = self.plugin.converter.schema2parameters(
                        actual_params["schema"],
                        required=actual_params.get("required", False),
                    )[0]
                    updated_params = {
                        k: v
                        for k, v in raw_parameters.items()
                        if k in VALID_RESPONSE_FIELDS
                    }
                    updated_params['schema'] = actual_params["schema"]
                    for extra_info in ("description", "headers", "examples"):
                        if extra_info in actual_params:
                            updated_params[extra_info] = actual_params[
                                extra_info]
                    responses[code] = updated_params
                else:
                    responses[code] = actual_params
            data["responses"] = responses

        operations = copy.deepcopy(data)
        self.spec.path(path=url_path, operations={method: operations})
Exemplo n.º 12
0
 def spec(self):
     return APISpec(
         title='Validation',
         version='0.1',
         plugins=['apispec.ext.marshmallow'],
     )
# -*- coding: utf-8 -*-
from apispec import APISpec
from marshmallow import Schema, fields


__all__ = ['spec']


spec = APISpec(
    title='mypackage',
    version='0.0.1',
    info=dict(
        description='${description}'
    ),
    plugins=['apispec.ext.marshmallow']
)


class PersonSchema(Schema):
  age = fields.Int()
  name = fields.String()
    
spec.definition('Person', schema=PersonSchema)


spec.add_path(
    path='/randomPerson',
    operations=dict(
        get=dict(
            responses={
                '${op.responses().success().code()}': {
Exemplo n.º 14
0
# Copyright European Organization for Nuclear Research (CERN) since 2012
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from apispec import APISpec
from apispec_webframeworks.flask import FlaskPlugin
from rucio.vcsversion import VERSION_INFO
from rucio.web.rest.flaskapi.v1.main import application

spec = APISpec(
    title="Rucio",
    version=VERSION_INFO['version'],
    openapi_version="3.0.2",
    plugins=[FlaskPlugin()],
)

with application.test_request_context():
    for view_func in application.view_functions.values():
        spec.path(view=view_func)
print(spec.to_yaml())
Exemplo n.º 15
0
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import FlaskPlugin
from marshmallow import Schema, fields
import os

service_url = os.getenv("SERVICE_URL", "http://localhost")

spec = APISpec(
    title="TimO Auswertung API",
    version="1.0.0",
    openapi_version="3.0.2",
    info=dict(description="TimO Auswertung API",
              version="1.0.0-oas3",
              contact=dict(email="*****@*****.**"),
              license=dict(
                  name="Apache 2.0",
                  url='http://www.apache.org/licenses/LICENSE-2.0.html')),
    servers=[dict(description="This API instance", url=service_url)],
    tags=[
        dict(name="TimO Auswertung",
             description="Endpoints related to TimO Auswertung")
    ],
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
)

# class DemoParameter(Schema):
#     gist_id = fields.Int()

# class DemoSchema(Schema):
#     id = fields.Int()
#     content = fields.Str()
Exemplo n.º 16
0
class WRAPISpec(object):
    RE_URL = re.compile(r'<(?:[^:<>]+:)?([^<>]+)>')

    tags = [
        {
            'name': 'Auth',
            'description': 'Auth and Login API'
        },
        {
            'name': 'Users',
            'description': 'User API'
        },
        {
            'name': 'Collections',
            'description': 'Collection API'
        },
        {
            'name': 'Recordings',
            'description': 'Recording Sessions Management API'
        },
        {
            'name': 'Lists',
            'description': 'List API'
        },
        {
            'name': 'Bookmarks',
            'description': 'Bookmarks API'
        },
        {
            'name': 'Browsers',
            'description': 'Browser API'
        },
        {
            'name': 'External Archives',
            'description': 'External Archives Info API'
        },
        {
            'name': 'Cookies',
            'description': 'Cookie Handling'
        },
        {
            'name': 'Bug Reporting',
            'description': 'Bug Reporting API'
        },
        {
            'name': 'Admin',
            'description': 'Admin API'
        },
        {
            'name': 'Stats',
            'description': 'Stats API'
        },
    ]

    string_params = {
        'user': '******',
        'username': '******',
        'coll': 'Collection Slug',
        'coll_name': 'Collection Slug',
        'rec': 'Session Id',
        'reqid': 'Remote Browser Request Id',
        'new_coll_name': 'New Collection Name',
        'list': 'List Id',
        'list_id': 'List Id',
        'bid': 'Bookmark Id',
        'title': 'Title',
        'desc': 'Description',
        'url': 'Archived Url',
        'timestamp': 'Archived at Timestamp',
        'browser': 'Browser Used',
        'page_id': 'Page Id',
        'upload_id': 'Upload Id',
    }

    opt_bool_params = {
        'public': 'Publicly Accessible',
        'include_recordings': 'Include Recording Sessions in response',
        'include_lists': 'Include all lists in response',
        'include_pages': 'Include pages in response',
        'include_bookmarks': 'Include bookmarks in response',
        'public_index': 'Publicly Accessible Collection Index',
    }

    custom_params = {
        'before_id': {
            'type': 'string',
            'description': 'Insert Before this Id',
        },
        'order': {
            'type': 'array',
            'items': {
                'type': 'string'
            },
            'description': 'an array of existing ids in new order'
        }
    }

    all_responses = {}

    @classmethod
    def bottle_path_to_openapi(cls, path):
        path_vars = cls.RE_URL.findall(path)
        path = cls.RE_URL.sub(r'{\1}', path)
        return path, path_vars

    def __init__(self, api_root):
        self.api_root = api_root
        self.api_map = defaultdict(dict)
        self.funcs = defaultdict(dict)

        self.curr_tag = ''

        self.spec = APISpec(title='Webrecorder',
                            version='1.0.0',
                            openapi_version='3.0.0',
                            info=dict(description='Webrecorder API'),
                            plugins=[])

        self.err_400 = self.make_err_response('Invalid Request Param')
        self.err_404 = self.make_err_response('Object Not Found')
        self.err_403 = self.make_err_response('Invalid Authorization')
        self.any_obj = self.make_any_response()

    def set_curr_tag(self, tag):
        self.curr_tag = tag

    def add_route(self, route):
        if route.rule.startswith(self.api_root):
            path, path_vars = self.bottle_path_to_openapi(route.rule)

            self.api_map[path][route.method.lower()] = route.callback

            self.funcs[route.callback]['path'] = path,
            self.funcs[route.callback]['path_params'] = self.make_params(
                path_vars, 'path')
            if self.curr_tag:
                self.funcs[route.callback]['tags'] = [self.curr_tag]

    def get_param(self, name):
        if name in self.string_params:
            param = {
                'description': self.string_params[name],
                'required': True,
                'schema': {
                    'type': 'string'
                },
                'name': name
            }

        elif name in self.opt_bool_params:
            param = {
                'description': self.opt_bool_params[name],
                'required': False,
                'schema': {
                    'type': 'boolean'
                },
                'name': name
            }

        elif name in self.custom_params:
            param = self.custom_params[name].copy()
            param['name'] = name

        else:
            raise AssertionError('Param {0} not found'.format(name))

        return param

    def get_req_param(self, name):
        if name in self.string_params:
            return {'type': 'string', 'description': self.string_params[name]}

        elif name in self.opt_bool_params:
            return {
                'type': 'boolean',
                'description': self.opt_bool_params[name]
            }

        elif name in self.custom_params:
            return self.custom_params[name]

        raise AssertionError('Param {0} not found'.format(name))

    def make_params(self, params, param_type):
        objs = []
        for param in params:
            obj = self.get_param(param)
            obj['in'] = param_type
            objs.append(obj)

        return objs

    def add_func(self, func, kwargs):
        query = kwargs.get('query')
        if query:
            self.funcs[func]['query_params'] = self.make_params(query, 'query')

        req = kwargs.get('req')
        if req:
            self.funcs[func]['request'] = self.get_request(
                req, kwargs.get('req_desc'))

    def get_request(self, req_props, req_desc=None):
        properties = {}

        schema = None

        # make array out of props
        if isinstance(req_props, dict):
            if req_props.get('type') == 'array':
                obj_type = 'array'
                prop_list = req_props['item_type']

            assert (prop_list)

        else:
            obj_type = 'object'
            prop_list = req_props

        if not schema:
            for prop in prop_list:
                properties[prop] = self.get_req_param(prop)

            schema = {'type': 'object', 'properties': properties}

            # wrap schema in array
            if obj_type == 'array':
                schema = {'type': 'array', 'items': schema}

        request = {'content': {'application/json': {'schema': schema}}}

        if req_desc:
            request['description'] = req_desc

        return request

    def build_api_spec(self):
        for name, routes in self.api_map.items():
            ops = {}
            for method, callback in routes.items():
                info = self.funcs[callback]

                # combine path params and query params, if any
                params = info.get('path_params', []) + info.get(
                    'query_params', [])

                api = {'parameters': params}

                # for POST and PUT, generate requestBody
                if method == 'post' or method == 'put':
                    request = info.get('request')
                    if request:
                        api['requestBody'] = request
                else:
                    # otherwise, ensure no request body!
                    assert 'request' not in info

                # set tags, if any
                if 'tags' in info:
                    api['tags'] = info['tags']

                api['responses'] = self.get_responses(None)

                ops[method] = api

            self.spec.add_path(path=name, operations=ops)

        for tag in self.tags:
            self.spec.add_tag(tag)

    def get_responses(self, obj_type):
        response_obj = self.all_responses.get(obj_type) or self.any_obj
        obj = {'400': self.err_400, '404': self.err_404, '200': response_obj}

        return obj

    def make_err_response(self, msg):
        obj = {
            'description': msg,
            'content': {
                'application/json': {
                    'schema': {
                        'type': 'object',
                        'properties': {
                            'error': {
                                'type': 'string'
                            }
                        }
                    }
                }
            }
        }

        return obj

    def make_any_response(self):
        obj = {
            'description': 'Any Object',
            'content': {
                'application/json': {
                    'schema': {
                        'type': 'object',
                        'additionalProperties': True
                    }
                }
            }
        }

        return obj

    def get_api_spec_yaml(self):
        return self.spec.to_yaml()
Exemplo n.º 17
0
    def api_spec(self):
        """
        OpenApi 2.0 spec
        ---
        get:
          tags:
          - "OpenApi 2.0 spec"
          summary: "Return openapi spec
          purposes"
          description: ""
          operationId: "api_spec"
          consumes:
          - "application/json"
          produces:
          - "application/json"
          parameters:
          responses:
            200:
              description: "Success"
        """
        spec = APISpec(
            title="Channelstream API",
            version="0.7.0",
            openapi_version="2.0.0",
            plugins=(MarshmallowPlugin(),),
        )
        spec.components.schema("ConnectBody", schema=schemas.ConnectBodySchema)
        spec.components.schema("SubscribeBody", schema=schemas.SubscribeBodySchema)
        spec.components.schema("UnsubscribeBody", schema=schemas.UnsubscribeBodySchema)
        spec.components.schema("UserStateBody", schema=schemas.UserStateBodySchema)
        spec.components.schema(
            "MessagesBody", schema=schemas.MessageBodySchema(many=True)
        )
        spec.components.schema("MessageBody", schema=schemas.MessageBodySchema())
        spec.components.schema(
            "MessageEditBody", schema=schemas.MessageEditBodySchema(many=True)
        )
        spec.components.schema(
            "MessagesDeleteBody", schema=schemas.MessagesDeleteBodySchema(many=True)
        )
        spec.components.schema("DisconnectBody", schema=schemas.DisconnectBodySchema)
        spec.components.schema("ChannelConfigBody", schema=schemas.ChannelConfigSchema)
        spec.components.schema("ChannelInfoBody", schema=schemas.ChannelInfoBodySchema)

        # api
        add_pyramid_paths(spec, "connect", request=self.request)
        add_pyramid_paths(spec, "subscribe", request=self.request)
        add_pyramid_paths(spec, "unsubscribe", request=self.request)
        add_pyramid_paths(spec, "user_state", request=self.request)
        add_pyramid_paths(spec, "message", request=self.request)
        add_pyramid_paths(spec, "channel_config", request=self.request)
        add_pyramid_paths(spec, "info", request=self.request)

        add_pyramid_paths(spec, "api_listen", request=self.request)
        add_pyramid_paths(spec, "api_listen_ws", request=self.request)
        add_pyramid_paths(spec, "api_disconnect", request=self.request)

        add_pyramid_paths(spec, "admin_json", request=self.request)
        spec_dict = spec.to_dict()
        spec_dict["securityDefinitions"] = {
            "APIKeyHeader": {
                "type": "apiKey",
                "name": "X-Channelstream-Secret",
                "in": "header",
            }
        }
        return spec_dict
Exemplo n.º 18
0
class WRAPISpec(object):
    RE_URL = re.compile(r'<(?:[^:<>]+:)?([^<>]+)>')

    tags = [
        {
            'name': 'WASAPI (Downloads)',
            'description': 'Download WARC files API (conforms to WASAPI spec)'
        },
        {
            'name': 'Auth',
            'description': 'Auth and Login API'
        },
        {
            'name': 'Users',
            'description': 'User API'
        },
        {
            'name': 'Collections',
            'description': 'Collection API'
        },
        {
            'name': 'doi',
            'description': 'DOI API'
        },
        {
            'name': 'Recordings',
            'description': 'Recording Sessions Management API'
        },
        {
            'name': 'Lists',
            'description': 'List API'
        },
        {
            'name': 'Bookmarks',
            'description': 'Bookmarks API'
        },
        {
            'name': 'Uploads',
            'description': 'Upload WARC or HAR files API'
        },
        {
            'name': 'Add External Records',
            'description': 'Add External WARC Records API'
        },
        {
            'name': 'Browsers',
            'description': 'Browser API'
        },
        {
            'name': 'External Archives',
            'description': 'External Archives Info API'
        },
        {
            'name': 'Cookies',
            'description': 'Cookie Handling'
        },
        {
            'name': 'Bug Reporting',
            'description': 'Bug Reporting API'
        },
        {
            'name': 'Admin',
            'description': 'Admin API',
        },
        {
            'name': 'Stats',
            'description': 'Stats API',
        },
        {
            'name': 'Automation',
            'description': 'Automation API',
        },
        {
            'name': 'Behaviors',
            'description': 'Behaviors API'
        },
    ]

    # only include these groups when logged in as admin
    admin_tags = ['Admin', 'Stats', 'Automation']

    string_params = {
        'user': '******',
        'username': '******',
        'coll': 'Collection Slug',
        'coll_name': 'Collection Slug',
        'collection': 'Collection Slug',
        'doi': 'DOI Slug',
        'rec': 'Session Id',
        'reqid': 'Remote Browser Request Id',
        'new_coll_name': 'New Collection Name',
        'list': 'List Id',
        'list_id': 'List Id',
        'bid': 'Bookmark Id',
        'autoid': 'Automation Id',
        'title': 'Title',
        'desc': 'Description',
        'url': 'Archived Url',
        'timestamp': 'Archived at Timestamp',
        'browser': 'Browser Used',
        'page_id': 'Page Id',
        'upload_id': 'Upload Id',
        'filename': 'File Name',
    }

    opt_bool_params = {
        'public': 'Publicly Accessible',
        'include_recordings': 'Include Recording Sessions in response',
        'include_lists': 'Include all lists in response',
        'include_pages': 'Include pages in response',
        'include_bookmarks': 'Include bookmarks in response',
        'public_index': 'Publicly Accessible Collection Index',
    }

    custom_params = {
        'before_id': {
            'type': 'string',
            'description': 'Insert Before this Id',
        },
        'order': {
            'type': 'array',
            'items': {
                'type': 'string'
            },
            'description': 'an array of existing ids in new order'
        }
    }

    all_responses = {
        'wasapi_list': {
            'description':
            'WASAPI response for list of WARC files available for download',
            'content': {
                'application/json': {
                    'schema': {
                        'type': 'object',
                        'properties': {
                            'files': {
                                'type': 'array',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'content-type': {
                                            'type': 'string'
                                        },
                                        'filetype': {
                                            'type': 'string'
                                        },
                                        'filename': {
                                            'type': 'string',
                                        },
                                        'size': {
                                            'type': 'integer'
                                        },
                                        'recording': {
                                            'type': 'string'
                                        },
                                        'recording_date': {
                                            'type': 'string'
                                        },
                                        'collection': {
                                            'type': 'string'
                                        },
                                        'checksums': {
                                            'type': 'object'
                                        },
                                        'locations': {
                                            'type': 'array',
                                            'items': {
                                                'type': 'string'
                                            }
                                        },
                                        'is_active': {
                                            'type': 'boolean'
                                        },
                                    }
                                }
                            },
                            'include-extra': {
                                'type': 'boolean'
                            }
                        }
                    }
                }
            }
        },
        'wasapi_download': {
            'description': 'WARC file',
            'content': {
                'application/warc': {
                    'schema': {
                        'type': 'string',
                        'format': 'binary',
                        'example': 'WARC/1.0\r\nWARC-Type: response\r\n...',
                    }
                }
            }
        }
    }

    @classmethod
    def bottle_path_to_openapi(cls, path):
        path_vars = cls.RE_URL.findall(path)
        path = cls.RE_URL.sub(r'{\1}', path)
        return path, path_vars

    def __init__(self, api_root):
        self.api_root = api_root
        self.api_map = defaultdict(dict)
        self.funcs = defaultdict(dict)

        self.curr_tag = ''

        self.spec = APISpec(
            title='Webrecorder',
            version='1.0.0',
            openapi_version='3.0.0',
            info=dict(
                description=
                'Webrecorder API. This API includes all features available and in use by the frontend.'
            ),
            plugins=[])

        self.admin_spec = APISpec(
            title='Webrecorder',
            version='1.0.0',
            openapi_version='3.0.0',
            info=dict(
                description=
                'Webrecorder API (including Admin). This API includes all features available in Webrecorder, including admin and stats APIs.'
            ),
            plugins=[])

        self.err_400 = self.make_err_response('Invalid Request Param')
        self.err_404 = self.make_err_response('Object Not Found')
        self.err_403 = self.make_err_response('Invalid Authorization')
        self.any_obj = self.make_any_response()

    def set_curr_tag(self, tag):
        self.curr_tag = tag

    def add_route(self, route):
        if route.rule.startswith(self.api_root):
            path, path_vars = self.bottle_path_to_openapi(route.rule)

            self.api_map[path][route.method.lower()] = route.callback

            self.funcs[route.callback]['path'] = path,
            self.funcs[route.callback]['path_params'] = self.make_params(
                path_vars, 'path')
            if self.curr_tag:
                self.funcs[route.callback]['tags'] = [self.curr_tag]

    def get_param(self, name):
        """Returns the open api description of the supplied query parameter name

        :param str name: The name of the query parameter
        :return: A dictionary containing the
        :rtype: dict
        """
        optional = name.startswith('?')
        if optional:
            name = name[1:]
        if name in self.string_params:
            param = {
                'description': self.string_params[name],
                'required': not optional,
                'schema': {
                    'type': 'string'
                },
                'name': name
            }

        elif name in self.opt_bool_params:
            param = {
                'description': self.opt_bool_params[name],
                'required': False,
                'schema': {
                    'type': 'boolean'
                },
                'name': name
            }

        elif name in self.custom_params:
            param = self.custom_params[name].copy()
            param['name'] = name

        else:
            raise AssertionError('Param {0} not found'.format(name))

        return param

    def get_req_param(self, name):
        if name in self.string_params:
            return {'type': 'string', 'description': self.string_params[name]}

        elif name in self.opt_bool_params:
            return {
                'type': 'boolean',
                'description': self.opt_bool_params[name]
            }

        elif name in self.custom_params:
            return self.custom_params[name]

        raise AssertionError('Param {0} not found'.format(name))

    def make_params(self, params, param_type):
        objs = []
        for param in params:
            obj = self.get_param(param)
            obj['in'] = param_type
            objs.append(obj)

        return objs

    def add_func(self, func, kwargs):
        query = kwargs.get('query')
        if query:
            self.funcs[func]['query_params'] = self.make_params(query, 'query')

        req = kwargs.get('req')
        if req:
            self.funcs[func]['request'] = self.get_request(
                req, kwargs.get('req_desc'))

        resp = kwargs.get('resp')
        if resp:
            self.funcs[func]['resp'] = resp

    def get_request(self, req_props, req_desc=None):
        properties = {}

        schema = None

        # make array out of props
        if isinstance(req_props, dict):
            if req_props.get('type') == 'array':
                obj_type = 'array'
                prop_list = req_props['item_type']

            assert (prop_list)

        else:
            obj_type = 'object'
            prop_list = req_props

        if not schema:
            for prop in prop_list:
                properties[prop] = self.get_req_param(prop)

            schema = {'type': 'object', 'properties': properties}

            # wrap schema in array
            if obj_type == 'array':
                schema = {'type': 'array', 'items': schema}

        request = {'content': {'application/json': {'schema': schema}}}

        if req_desc:
            request['description'] = req_desc

        return request

    def build_api_spec(self):
        for name, routes in self.api_map.items():
            ops = {}
            for method, callback in routes.items():
                info = self.funcs[callback]

                # combine path params and query params, if any
                params = info.get('path_params', []) + info.get(
                    'query_params', [])

                api = {'parameters': params}

                # for POST and PUT, generate requestBody
                if method == 'post' or method == 'put':
                    request = info.get('request')
                    if request:
                        api['requestBody'] = request
                else:
                    # otherwise, ensure no request body!
                    assert 'request' not in info

                # set tags, if any
                if 'tags' in info:
                    api['tags'] = info['tags']
                    is_admin = info['tags'][0] in self.admin_tags

                api['responses'] = self.get_responses(info.get('resp', None))

                ops[method] = api

            if not is_admin:
                self.spec.add_path(path=name, operations=ops)

            self.admin_spec.add_path(path=name, operations=ops)

        for tag in self.tags:
            self.admin_spec.add_tag(tag)

            if tag['name'] not in self.admin_tags:
                self.spec.add_tag(tag)
            else:
                print('skip', tag)

    def get_responses(self, obj_type):
        response_obj = self.all_responses.get(obj_type) or self.any_obj
        obj = {'400': self.err_400, '404': self.err_404, '200': response_obj}

        return obj

    def make_err_response(self, msg):
        obj = {
            'description': msg,
            'content': {
                'application/json': {
                    'schema': {
                        'type': 'object',
                        'properties': {
                            'error': {
                                'type': 'string'
                            }
                        }
                    }
                }
            }
        }

        return obj

    def make_any_response(self):
        obj = {
            'description': 'Any Object',
            'content': {
                'application/json': {
                    'schema': {
                        'type': 'object',
                        'additionalProperties': True
                    }
                }
            }
        }

        return obj

    def get_api_spec_yaml(self, use_admin=False):
        """Returns the api specification as a yaml string

        :return: The api specification as a yaml string
        :rtype: str
        """
        return self.spec.to_yaml(
        ) if not use_admin else self.admin_spec.to_yaml()

    def get_api_spec_dict(self, use_admin=False):
        """Returns the api specification as a dictionary

        :return: The api specification as a dictionary
        :rtype: dict
        """
        return self.spec.to_dict(
        ) if not use_admin else self.admin_spec.to_dict()
Exemplo n.º 19
0
# Setup API docs and Swagger
from .core import app
from .auth import add_auth_to_swagger
from apispec import APISpec
from flask_apispec.extension import FlaskApiSpec
from webargs import fields
from apispec.ext.marshmallow import MarshmallowPlugin

file_plugin = MarshmallowPlugin()
spec = APISpec(title='neuroscout',
               version='v1',
               plugins=[file_plugin],
               openapi_version='2.0')
app.config.update({'APISPEC_SPEC': spec})
add_auth_to_swagger(spec)

docs = FlaskApiSpec(app)


@file_plugin.map_to_openapi_type('file', None)
class FileField(fields.Raw):
    pass
Exemplo n.º 20
0
from arcor2.source.logic import program_src  # , get_logic_from_source
from arcor2.source.utils import derived_resources_class, global_action_points_class, global_actions_class

PORT = int(os.getenv("ARCOR2_BUILD_PORT", 5008))
SERVICE_NAME = "ARCOR2 Build Service"

logger = logging.getLogger("build")
ch = logging.StreamHandler()
ch.setFormatter(logger_formatter())
logger.setLevel(logging.INFO)
logger.addHandler(ch)

# Create an APISpec
spec = APISpec(
    title=SERVICE_NAME,
    version=arcor2.version(),
    openapi_version="3.0.2",
    plugins=[FlaskPlugin()],
)

app = Flask(__name__)
CORS(app)


def _publish(project_id: str, package_name: str):

    with tempfile.TemporaryDirectory() as tmpdirname:

        try:
            project = ps.get_project(project_id)
            scene = ps.get_scene(project.scene_id)
Exemplo n.º 21
0
migrate = Migrate(directory="./api/migrations")

spec = APISpec(
    title="Large app - APIv1",
    description="## Our API",
    version="v1",
    swagger="2.0",
    openapi_version="2.0",
    plugins=[MarshmallowPlugin()],
    securityDefinitions={
        "httpBasic": {
            "type": "basic",
            "description": (
                "Authorization providing access to the "
                "backend. Currently only standard Basic "
                "Authentication is supported"
            ),
        },
        "auth0": {
            "type": "oauth2",
            "flow": "implicit",
            "authorizationUrl": (
                "https://trueenergy.eu.auth0.com/authorize"
                "?audience=apiv2.auth0.do.trnrg.co"
            ),
        },
    },
)


def create_app():
Exemplo n.º 22
0
from flask import Flask
from flask_restful import Resource, Api
from apispec import APISpec
from marshmallow import Schema, fields
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec.extension import FlaskApiSpec
from flask_apispec.views import MethodResource
from flask_apispec import marshal_with, doc, use_kwargs

app = Flask(__name__)  # Flask app instance initiated
api = Api(app)  # Flask restful wraps Flask app around it.
app.config.update({
    'APISPEC_SPEC':
    APISpec(title='Awesome Project',
            version='v1',
            plugins=[MarshmallowPlugin()],
            openapi_version='2.0.0'),
    'APISPEC_SWAGGER_URL':
    '/swagger/',  # URI to access API Doc JSON
    'APISPEC_SWAGGER_UI_URL':
    '/swagger-ui/'  # URI to access UI of API Doc
})
docs = FlaskApiSpec(app)


class AwesomeResponseSchema(Schema):
    message = fields.Str(default='Success')


class AwesomeRequestSchema(Schema):
    api_type = fields.String(required=True,
Exemplo n.º 23
0
from apispec_webframeworks.flask import FlaskPlugin

from flask_base.utils import (
    function_args,
    http_path,
    find_schemas,
    http_methods,
)
from py_tools.format import dumps, loads

mm_plugin = MarshmallowPlugin()
flask_plugin = FlaskPlugin()

api_spec = APISpec(
    title="",
    version="1.0.0",
    openapi_version="2.0",
    plugins=(mm_plugin, flask_plugin),
)


def generate_swagger(cls):
    def update_nested(orig_dict, new_dict):
        """Update nested dictionary"""
        for key, value in new_dict.items():
            if isinstance(value, Mapping):
                tmp = update_nested(orig_dict.get(key, {}), value)
                orig_dict[key] = tmp
            elif isinstance(value, list):
                orig_dict[key] = orig_dict.get(key, []) + value
            else:
                orig_dict[key] = new_dict[key]
Exemplo n.º 24
0
        return ""

    formatted = []
    lines = docstring.expandtabs().splitlines()

    for line in lines:
        if line == "":
            formatted.append("\n\n")
        else:
            formatted.append(line.strip())

    return " ".join(formatted).strip()


TAGS = [
    {
        "name": "Example",
        "description": format_docstring(docs.COVID_TAG)
    },
]

APISPEC_SPEC = APISpec(
    title="COVID Contact Tracing API",
    version="v1",
    info={"description": format_docstring(docs.API_DESCRIPTION)},
    plugins=[MarshmallowPlugin()],
    produces=["application/json"],
    openapi_version="2.0.0",
    tags=TAGS,
)
Exemplo n.º 25
0
def create_app(script_info=None):
 
    # instantiate the app
    app = Flask(
        __name__,
        template_folder='templates',
        static_folder='static'
    )

    # sys.modules[__name__]._current_app = app

    # set config
    app_settings = os.getenv("FLASK_APP_CONFIG", "qctrl_api.config.DevelopmentConfig")
    app.config.from_object(app_settings)

    app.config.update({
        'APISPEC_SPEC': APISpec(
            title='Q-CTRL API',
            info=qdict(
                # description=open('API.md').read(),
            ),
            basePath="/api",
            version=__version__,
            plugins=[
                # FlaskPlugin(),
                MarshmallowPlugin(),
            ],
        ),
    })

    _app_logger.info("FlaskConfig: {}".format(app.config))

    # Register custom error handler so we can see what is exactly failing at validation.
    app.errorhandler(422)(handle_unprocessable_entity)
    app.errorhandler(ValidationError)(handle_validation_error)

    # Add spec handler to app so we don't need to pass it around separately.
    app.docs = FlaskApiSpec(app)

    # set up extensions
    # login_manager.init_app(app)
    # bcrypt.init_app(app)
    toolbar.init_app(app)
    # bootstrap.init_app(app)
    db.init_app(app)
    # migrate.init_app(app, db)
    
    # CORS Plugin init
    CORS(app)

    # # flask login
    # from project.server.models import User
    # login_manager.login_view = 'user.login'
    # login_manager.login_message_category = 'danger'

    # @login_manager.user_loader
    # def load_user(user_id):
    #     return User.query.filter(User.id == int(user_id)).first()

    # # error handlers
    # @app.errorhandler(401)
    # def unauthorized_page(error):
    #     return render_template('errors/401.html'), 401

    # @app.errorhandler(403)
    # def forbidden_page(error):
    #     return render_template('errors/403.html'), 403

    # @app.errorhandler(404)
    # def page_not_found(error):
    #     return render_template('errors/404.html'), 404

    # @app.errorhandler(500)
    # def server_error_page(error):
    #     return render_template('errors/500.html'), 500

    # shell context for flask cli
    @app.shell_context_processor
    def ctx():
        return {
            "app": app,
        }

    return app
Exemplo n.º 26
0
def test_openapi_tools_validate_v3():
    ma_plugin = MarshmallowPlugin()
    spec = APISpec(
        title='Pets',
        version='0.1',
        plugins=(ma_plugin, ),
        openapi_version='3.0.0',
    )
    #openapi = ma_plugin.openapi

    spec.definition('Category', schema=CategorySchema)
    spec.definition('Pet', schema=PetSchemaV3)

    spec.add_path(
        view=None,
        path='/category/{category_id}',
        operations={
            'get': {
                'parameters': [
                    {
                        'name': 'q',
                        'in': 'query',
                        'schema': {
                            'type': 'string'
                        },
                    },
                    {
                        'name': 'category_id',
                        'in': 'path',
                        'required': True,
                        'schema': {
                            'type': 'string'
                        },
                    },
                ],  # + openapi.schema2parameters(PageSchema, default_in='query'),
                'responses': {
                    200: {
                        'description': 'success',
                        'content': {
                            'application/json': {
                                'schema': PetSchemaV3,
                            },
                        },
                    },
                },
            },
            'post': {
                'parameters': ([
                    {
                        'name': 'category_id',
                        'in': 'path',
                        'required': True,
                        'schema': {
                            'type': 'string'
                        },
                    },
                ]),
                'requestBody': {
                    'content': {
                        'application/json': {
                            'schema': CategorySchema,
                        },
                    },
                },
                'responses': {
                    201: {
                        'description': 'created',
                        'content': {
                            'application/json': {
                                'schema': PetSchemaV3,
                            },
                        },
                    },
                },
            },
        },
    )
    try:
        utils.validate_spec(spec)
    except exceptions.OpenAPIError as error:
        pytest.fail(str(error))
class AiohttpApiSpec:
    def __init__(
        self, url="/api/docs/api-docs", app=None, request_data_name="data", **kwargs
    ):
        warnings.warn(
            "'AiohttpApiSpec' will be removed since '1.0.0' version"
            " of 'aiohttp-apispec', use 'setup_aiohttp_apispec' instead",
            PendingDeprecationWarning,
        )
        self.spec = APISpec(**kwargs)
        if "apispec.ext.marshmallow" not in self.spec.plugins:
            self.spec.setup_plugin("apispec.ext.marshmallow")
        self.url = url
        self._registered = False
        self._request_data_name = request_data_name
        if app is not None:
            self.register(app)

    def swagger_dict(self):
        return self.spec.to_dict()

    def register(self, app: web.Application):
        if self._registered is True:
            return None
        app["_apispec_request_data_name"] = self._request_data_name

        async def doc_routes(app_):
            self._register(app_)

        app.on_startup.append(doc_routes)
        self._registered = True

        def swagger_handler(request):
            return web.json_response(request.app["swagger_dict"])

        app.router.add_routes([web.get(self.url, swagger_handler)])

    def _register(self, app: web.Application):
        for route in app.router.routes():
            if issubclass_py37fix(route.handler, web.View) and route.method == METH_ANY:
                for attr in dir(route.handler):
                    if attr.upper() in METH_ALL:
                        view = getattr(route.handler, attr)
                        method = attr
                        self._register_route(route, method, view)
            else:
                method = route.method.lower()
                view = route.handler
                self._register_route(route, method, view)
        app["swagger_dict"] = self.swagger_dict()

    def _register_route(self, route: web.RouteDef, method, view):

        if not hasattr(view, "__apispec__"):
            return None

        url_path = get_path(route)
        if not url_path:
            return None

        view.__apispec__["parameters"].extend(
            {"in": "path", "name": path_key, "required": True, "type": "string"}
            for path_key in get_path_keys(url_path)
        )
        self._update_paths(view.__apispec__, method, url_path)

    def _update_paths(self, data: dict, method: str, url_path: str):
        operations = copy.deepcopy(data)

        if method in PATHS:
            self.spec.add_path(Path(path=url_path, operations={method: operations}))
from apispec import APISpec

from starlette.applications import Starlette
from starlette.endpoints import HTTPEndpoint
from starlette.testclient import TestClient

from starlette_apispec import APISpecSchemaGenerator


app = Starlette()

schemas = APISpecSchemaGenerator(
    APISpec(
        title="Example API",
        version="1.0",
        openapi_version="3.0.0",
        info={"description": "explanation of the api purpose"},
    )
)


@app.websocket_route("/ws")
def ws(session):
    """ws"""
    pass  # pragma: no cover


@app.route("/users", methods=["GET", "HEAD"])
def list_users(request):
    """
    responses:
Exemplo n.º 29
0
from starlette_apispec import APISpecSchemaGenerator  # type: ignore

import sys

sys.path.insert(1, '..')
sys.path.insert(2, '.')

from twigator.db.connection import MongoConnection
from twigator.db.aggregations import get_tweet_count, get_top_hashtags, get_top_twitters
from twigator.db.queries import get_last_tweets, get_tweet_by_id, get_author_by_id

SCHEMAS = APISpecSchemaGenerator(
    APISpec(
        title="Tweet query API",
        version="1.0",
        openapi_version="3.0.0",
        info={
            "description": "Aggregate tweets and provide RESTful access to DB"
        },
    ))

APP = Starlette(debug=True)


class ResponseBuilder:
    """
    Starlette Response builder.
    Uses UJSONResponse underneath.
    """
    def __init__(self) -> None:
        self.__response: dict = {}
Exemplo n.º 30
0
from apispec import APISpec
from apispec_webframeworks.flask import FlaskPlugin
import tempfile
from geometry_service.database import db
from ._version import __version__
from .api.doc_components import add_components
from .loggers import logger

# OpenAPI documentation
logger.debug('Initializing OpenAPI specification.')
spec = APISpec(
    title="Geometry API",
    version=__version__,
    info=dict(description=__doc__, contact={"email":
                                            "*****@*****.**"}),
    externalDocs={
        "description": "GitHub",
        "url": "https://github.com/OpertusMundi/geometry-service"
    },
    openapi_version="3.0.2",
    plugins=[FlaskPlugin()],
)
logger.debug('Adding OpenAPI specification components.')
add_components(spec)

# Check environment variables
if os.getenv('DATABASE_URI') is None:
    logger.fatal('Environment variable not set [variable="DATABASE_URI"]')
    sys.exit(1)
if os.getenv('SECRET_KEY') is None:
    logger.fatal('Environment variable not set [variable="SECRET_KEY"]')
    sys.exit(1)
Exemplo n.º 31
0
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin

TESTING = True
DEBUG = True
MONGO_DBS = ['test1', 'test2']
MONGODB_SETTINGS = [{
    'alias': db,
    'db': db,
    'host': 'mongo'
} for db in MONGO_DBS]
APISPEC_SPEC = APISpec(title="My API",
                       version='v1',
                       plugins=[MarshmallowPlugin()],
                       openapi_version='2.0')
Exemplo n.º 32
0
cors = CORS(allow_all_origins=['http://localhost:3000'])
app = falcon.API(
    middleware=[TokenAuthenticator(), cors.middleware,
                Iface_watch(), prom])

app.add_route('/', DefaultRouteHandler())
app.add_route('/fast-serve', FastServe())
app.add_route('/login', IctrlProtonLogin())
app.add_route('/signup', IctrlProtonSignup())
app.add_route('/metrics', prom)
app.add_route('/proton-prom', RedirectToProm())
app.add_route('/proton-grafana', RedirectToGrafana())

# Open API Specs
spec = APISpec(
    title='PROTON STACK',
    version='1.0.0',
    openapi_version='2.0',
    plugins=[
        FalconPlugin(app),
    ],
)

# OPEN API specs will be generated during runtime.
with open('{}/mic/iface/openApi/specs.json'.format(ProtonConfig().ROOT_DIR),
          'w+') as sjf:
    sjf.write(json.dumps(spec.to_dict()))

with open('{}/mic/iface/openApi/specs.yaml'.format(ProtonConfig().ROOT_DIR),
          'w+') as syf:
    syf.write(spec.to_yaml())
Exemplo n.º 33
0
        responses:
            200:
                description: A pet to be returned
                schema: PetSchema
        """
        pet = get_random_pet()  # returns JSON
        resp.media = pet


# create instance of resource
random_pet_resource = RandomPetResource()
# pass into `add_route` for Falcon
app.add_route("/random", random_pet_resource)

# Create an APISpec
spec = APISpec(
    title='Swagger Petstore',
    version='1.0.0',
    openapi_version='2.0',
    plugins=[
        FalconPlugin(app),
        MarshmallowPlugin(),
    ],
)

# Register entities and paths
spec.components.schema('Category', schema=CategorySchema)
spec.components.schema('Pet', schema=PetSchema)
# pass created resource into `path` for APISpec
spec.path(resource=random_pet_resource)
class GenerateApiSpec(ffd.ApplicationService):
    _context_map: ffd.ContextMap = None

    def __init__(self):
        self._schemas = []

    def __call__(self, tag: str = None, **kwargs):
        try:
            from apispec import APISpec
            from docstring_parser import parse
        except ModuleNotFoundError:
            raise ffd.MissingDependency(
                'This feature requires "apispec" and "docstring_parser"')

        self._spec = APISpec(
            title='Testing Spec',
            version='1.0.0',
            openapi_version='3.0.2',
        )

        for context in self._context_map.contexts:
            prefix = f'/{inflection.dasherize(context.name)}'
            for endpoint in context.endpoints:
                if isinstance(endpoint, ffd.HttpEndpoint):
                    if tag is not None and tag not in endpoint.tags:
                        continue
                    docstring = parse(endpoint.service.__call__.__doc__)
                    short_description = docstring.short_description \
                        if docstring.short_description != 'Call self as a function.' else None

                    path = endpoint.route
                    if not path.startswith(prefix):
                        path = f'{prefix}{path}'

                    request_body = self._request_body(endpoint)
                    method = endpoint.method.lower()
                    operations = {method: {}}
                    if request_body is not None:
                        operations[method]['requestBody'] = request_body
                    self._spec.path(path=path,
                                    operations=operations,
                                    parameters=self._parameter_list(endpoint))

        print(json.dumps(self._spec.to_dict(), indent=2))

    def _parameter_list(self, endpoint: ffd.HttpEndpoint):
        ret = []
        if inspect.isclass(endpoint.service) and issubclass(
                endpoint.service, ffd.AggregateRoot):
            if endpoint.method.lower() == 'post':
                return [{
                    'name':
                    field_.name,
                    'in':
                    'TODO',
                    'description':
                    'TODO',
                    'required':
                    'required' in field_.metadata
                    and field_.metadata['required'] is True,
                    'schema': {
                        'type': field_.type,
                    }
                } for field_ in list(
                    filter(lambda f: not f.name.startswith('_'),
                           fields(endpoint.service)))]

    def _request_body(self, endpoint: ffd.HttpEndpoint):
        if not inspect.isclass(endpoint.service):
            return None

        if endpoint.method.lower() in ('post', 'put', 'patch'):
            return {
                'required': True,
                'content': {
                    'application/json': {
                        'schema': {
                            '$ref':
                            f'#/components/schemas/{self._add_schema(endpoint.service)}'
                        }
                    }
                }
            }

    def _add_schema(self, cls: typing.Union[Type[ffd.ValueObject],
                                            Type[ffd.ApplicationService]]):
        try:
            if cls.__name__ in self._schemas:
                return cls.__name__
        except AttributeError:
            pass

        if issubclass(cls, ffd.ValueObject):
            return self._add_entity_schema(cls)
        elif issubclass(cls, ffd.ApplicationService):
            return self._add_service_body_schema(cls)

    def _add_service_body_schema(self, cls: Type[ffd.ApplicationService]):
        props = {}
        signature = inspect.signature(cls.__call__)
        hints = typing.get_type_hints(cls.__call__)
        for name, param in signature.parameters.items():
            if name == 'self' or param.kind in (
                    inspect.Parameter.VAR_POSITIONAL,
                    inspect.Parameter.VAR_KEYWORD):
                continue
            try:
                type_ = hints[name]
            except KeyError:
                type_ = str
            self._handle_type(name, type_, props)

        self._spec.components.schema(cls.__name__, {'properties': props})
        self._schemas.append(cls.__name__)
        return cls.__name__

    def _add_entity_schema(self, cls: Type[ffd.ValueObject]):
        props = {}
        hints = typing.get_type_hints(cls)
        if not is_dataclass(cls):
            return None
        for field_ in fields(cls):
            if field_.name.startswith('_'):
                continue
            type_ = hints[field_.name]
            self._handle_type(field_.name, type_, props)

        self._spec.components.schema(cls.__name__, {'properties': props})
        self._schemas.append(cls.__name__)
        return cls.__name__

    def _handle_type(self, name: str, type_: type, props: dict):
        if inspect.isclass(type_) and issubclass(
                type_, (ffd.Entity, ffd.ValueObject)):
            props[name] = {
                'type': {
                    'schema': {
                        '$ref':
                        f'#/components/schemas/{self._add_schema(type_)}'
                    }
                }
            }
        elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.List:
            t = ffd.get_args(type_)[0]
            props[name] = {
                'type': 'array',
                'items': {
                    '$ref': f'#/components/schemas/{self._add_schema(t)}'
                }
            }
        elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.Union:
            args = ffd.get_args(type_)
            if args[1] is None:
                props[name] = self._map_type(args[0])
                props[name].update({'required': False})
        elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.Dict:
            props[name] = {'type': 'object'}
        else:
            props[name] = self._map_type(type_)

    def _map_type(self, type_: type):
        if type_ is str or type_ == 'str':
            return {'type': 'string'}
        elif type_ is int or type_ == 'int':
            return {'type': 'integer'}
        elif type_ is float or type_ == 'float':
            return {'type': 'number'}
        elif type_ is bool or type_ == 'bool':
            return {'type': 'boolean'}
        elif type_ is list or type_ == 'list':
            return {'type': 'array'}
        elif type_ is dict or type_ == 'dict':
            return {'type': 'object'}
        elif type_ is datetime or type_ == 'datetime':
            return {'type': 'string', 'format': 'date-time'}
        elif type_ is date or type_ == 'date':
            return {'type': 'string', 'format': 'date'}

        raise Exception(f"Don't know how to handle type: {type_}")
Exemplo n.º 35
0
API_DESCRIPTION = """
This is the documentation for the BubBug http service, the platform for Bugzilla Machine Learning projects.

# Introduction

This service can be used to classify a given bug using a pre-trained model.
You can classify a single bug or a batch of bugs.
The classification happens in the background so you need to call back the service for getting the results.
"""

spec = APISpec(
    title="Bugbug",
    version=get_bugbug_version(),
    openapi_version="3.0.2",
    info=dict(description=API_DESCRIPTION),
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
    security=[{
        "api_key": []
    }],
)

application = Flask(__name__)
redis_url = os.environ.get("REDIS_URL", "redis://localhost/0")
redis_conn = Redis.from_url(redis_url)

# Kill jobs which don't finish within 12 minutes.
JOB_TIMEOUT = 12 * 60
# Kill Bugzilla jobs which don't finish within 5 minutes.
BUGZILLA_JOB_TIMEOUT = 5 * 60
# Remove jobs from the queue if they haven't started within 7 minutes.
QUEUE_TIMEOUT = 7 * 60
Exemplo n.º 36
0
def spec():
    return APISpec(title='Swagger Petstore',
                   version='1.0.0',
                   description=description,
                   plugins=['apispec.ext.marshmallow'])
Exemplo n.º 37
0
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin

spec = APISpec(
    title="SAM apispec",
    version="0.0.1",
    openapi_version="3.0.3",
    plugins=[MarshmallowPlugin()],
)
Exemplo n.º 38
0
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import FlaskPlugin
from flask import Flask
from libtrustbridge.utils.specs import register_specs

from intergov.apis.common.errors import handlers
from intergov.apis.message import message, index
from intergov.apis.message.conf import Config

spec = APISpec(
    title="Message API",
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[
        FlaskPlugin(),
        MarshmallowPlugin(),
    ],
)


def create_app(config_object=None):
    """
    FLASK_ENV=development FLASK_APP=message_api.app flask run --port=5001
    """
    if config_object is None:
        config_object = Config
    app = Flask(__name__)
    app.config.from_object(config_object)
    SENTRY_DSN = app.config.get("SENTRY_DSN")
    if SENTRY_DSN:
Exemplo n.º 39
0
if getenv('OUTPUT_DIR') is None:
    raise OutputDirNotSet('Environment variable OUTPUT_DIR is not set.')

FILE_NOT_FOUND_MESSAGE = "File not found"

# Logging
mainLogger, accountLogger = getLoggers()

# OpenAPI documentation
spec = APISpec(
    title="Clustering and Outlier Detection API",
    version=getenv('VERSION'),
    info=dict(description="", contact={"email": ""}),
    externalDocs={
        "description": "GitHub",
        "url": "https://github.com/OpertusMundi/clustering-outliers-service"
    },
    openapi_version="3.0.2",
    plugins=[FlaskPlugin()],
)

# Initialize app
app = Flask(__name__,
            instance_relative_config=True,
            instance_path=getenv('INSTANCE_PATH'))
environment = getenv('FLASK_ENV')
if environment == 'testing' or environment == 'development':
    secret_key = environment
else:
    secret_key = getenv('SECRET_KEY') or open(getenv('SECRET_KEY_FILE')).read()