Example #1
0
def path_from_view(spec, app, view, **kwargs):
    """Path helper that allows passing a Chalice view function."""
    kwarg_ops = kwargs.get('operations')
    kwarg_ops = set() if not kwarg_ops else set(kwarg_ops)

    uri, methods = _route_for_view(app,
                                   view,
                                   path=kwargs.get('path', Path()),
                                   operations=kwarg_ops)
    operations = load_operations_from_docstring(view.__doc__)
    if not operations:
        operations = {}

    # check that the operations in the docstring match those of the actual route decorator
    path = Path(path=uri,
                operations={
                    method: op
                    for method, op in iteritems(operations)
                    if method in methods
                })

    # add methods from route decorator that were not in docstring
    for op in methods:
        path.operations.setdefault(op, {})

    return path
    def _update_paths(self, data: dict, method, url_path):
        operations = copy.deepcopy(data)
        operations.pop('docked', None)

        if method in PATHS:
            self.spec.add_path(
                Path(path=url_path, operations={method: operations}))
Example #3
0
def path_from_router(spec, view, operations, **kwargs):
    """Path helper that allows passing a bottle view function."""
    operations = utils.load_operations_from_docstring(view.__doc__)
    app = kwargs.get('app', _default_app)
    route = _route_for_view(app, view)
    bottle_path = bottle_path_to_swagger(route.rule)
    return Path(path=bottle_path, operations=operations)
Example #4
0
def path_from_view(spec, view, rule, **kwargs):
    """Path helper that allows passing a Werkzeug view function."""
    path = werkzeugpath2swagger(rule.rule)
    path = urllib.parse.urljoin('/', path.lstrip('/'))
    operations = utils.load_operations_from_docstring(view.__doc__)
    path = Path(path=path, operations=operations)
    return path
Example #5
0
def path_from_view(spec, view, operations, **kwargs):
    """Path helper that allows passing a Flask view function."""
    rule = _rule_for_view(view)
    path = flaskpath2swagger(rule.rule)
    operations = utils.load_operations_from_docstring(view.__doc__)
    path = Path(path=path, operations=operations)
    return path
Example #6
0
    def test_add_path_accepts_path(self, spec):
        route = '/pet/{petId}'
        route_spec = self.paths[route]
        path = Path(path=route, operations={'get': route_spec['get']})
        spec.add_path(path)

        p = spec._paths[path.path]
        assert p == path.operations
        assert 'get' in p
Example #7
0
def path_from_view(spec, view, **kwargs):
    """Path helper that allows passing a Flask view function."""
    rule = _rule_for_view(view)
    path = flaskpath2swagger(rule.rule)
    app_root = current_app.config['APPLICATION_ROOT'] or '/'
    path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/'))
    operations = utils.load_operations_from_docstring(view.__doc__)
    path = Path(path=path, operations=operations)
    return path
 def _update_paths(self, data: dict, method: str, url_path: str):
     if method in PATHS:
         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)
         operations = copy.deepcopy(data)
         self.spec.add_path(
             Path(path=url_path, operations={method: operations}))
Example #9
0
def path_from_route(spec, route, operations, **kwargs):
    """Path helper that allows passing a webapp2 Route or tuple."""
    if not isinstance(route, BaseRoute):
        route = Route(*route)
    if operations is None:
        operations = {}
        for operation in _operations_from_methods(route.handler):
            operations.update(operation)
    if not operations:
        raise APISpecError(
            'Could not find endpoint for route {0}'.format(route))
    params_method = getattr(route.handler, list(operations.keys())[0])
    path = webapp2_path_to_swagger(route, params_method)
    extensions = _extensions_from_handler(route.handler)
    operations.update(extensions)
    return Path(path=path, operations=operations)
Example #10
0
def path_from_urlspec(spec, urlspec, operations, **kwargs):
    """Path helper that allows passing a Tornado URLSpec or tuple."""
    if not isinstance(urlspec, URLSpec):
        urlspec = URLSpec(*urlspec)
    if operations is None:
        operations = {}
        for operation in _operations_from_methods(urlspec.handler_class):
            operations.update(operation)
    if not operations:
        raise APISpecError(
            'Could not find endpoint for urlspec {0}'.format(urlspec))
    params_method = getattr(urlspec.handler_class, list(operations.keys())[0])
    path = tornadopath2swagger(urlspec, params_method)
    extensions = _extensions_from_handler(urlspec.handler_class)
    operations.update(extensions)
    return Path(path=path, operations=operations)
Example #11
0
    def path_helper(self, app, rule, operations=None, **kwargs):
        """Make Path from flask Rule"""
        path = self.flaskpath2openapi(rule.rule)
        app_root = app.config['APPLICATION_ROOT'] or '/'
        path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/'))

        if operations:
            # Get path parameters
            path_parameters = self.rule_to_params(rule)
            if path_parameters:
                for operation in operations.values():
                    parameters = operation.setdefault('parameters', [])
                    # Add path parameters to documentation
                    for path_p in path_parameters:
                        parameters.append(path_p)

        return Path(path=path, operations=operations)
Example #12
0
def path_from_view(spec, view, **kwargs):
    """Path helper that allows passing a Flask view function."""
    rule = _rule_for_view(view)
    path = flaskpath2swagger(rule.rule)
    app_root = current_app.config['APPLICATION_ROOT'] or '/'
    path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/'))
    operations = utils.load_operations_from_docstring(view.__doc__)
    path = Path(path=path, operations=operations)
    if hasattr(view, 'view_class') and issubclass(view.view_class, MethodView):
        operations = {}
        for method in view.methods:
            method_name = method.lower()
            method = getattr(view.view_class, method_name)
            docstring_yaml = utils.load_yaml_from_docstring(method.__doc__)
            operations[method_name] = docstring_yaml or dict()
        path.operations.update(operations)
    return path
Example #13
0
    def path_helper(self, rule, operations=None, **kwargs):
        """Get path from flask Rule and set path parameters in operations"""
        path = self.flaskpath2openapi(rule.rule)

        if operations:
            # Get path parameters
            path_parameters = self.rule_to_params(rule)
            if path_parameters:
                for operation in operations.values():
                    parameters = operation.setdefault('parameters', [])
                    # Add path parameters to documentation
                    for path_p in path_parameters:
                        parameters.append(path_p)

        if APISPEC_VERSION_MAJOR == 0:
            return Path(path=path, operations=operations)
        return path
Example #14
0
def path_helper(_spec, **kwargs):
    """Extracts swagger spec from `flask-restful` methods."""
    try:
        resource = kwargs.pop('resource')

        path = deduce_path(resource, **kwargs)

        # normalize path
        path = re.sub(r'<(?:[^:<>]+:)?([^<>]+)>', r'{\1}', path)

        operations = parse_operations(resource)

        return Path(path=path, operations=operations)
    except Exception as exc:
        logging.getLogger(__name__).exception("Exception parsing APISpec %s",
                                              exc)
        raise
Example #15
0
def flask_path_helper(spec, app, rule, operations=None, **kwargs):

    path = flaskpath2swagger(rule.rule)
    app_root = app.config['APPLICATION_ROOT'] or '/'
    path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/'))

    if operations:
        # Get path parameters
        path_parameters = rule_to_params(rule)
        if path_parameters:
            for operation in operations.values():
                parameters = operation.setdefault('parameters', list())
                # Add path parameters to documentation
                # If a parameter is already in the doc (because it appears in
                # the parameters schema), merge properties rather than
                # duplicate or replace
                for path_p in path_parameters:
                    op_p = next((x for x in parameters
                                 if x['name'] == path_p['name']),
                                None)
                    if op_p is not None:
                        op_p.update(path_p)
                    else:
                        parameters.append(path_p)
        # Translate Marshmallow Schema
        for operation in operations.values():
            for response in operation.get('responses', {}).values():
                if 'schema' in response:
                    # If the API returns a list,
                    # the schema is specfied as [schema]
                    if isinstance(response['schema'], list):
                        response['schema'] = [
                            resolve_schema_dict(spec, response['schema'][0])
                        ]
                    else:
                        response['schema'] = resolve_schema_dict(
                            spec, response['schema'])

            for parameter in operation.get('parameters', []):
                if 'schema' in parameter:
                    parameter['schema'] = resolve_schema_dict(
                        spec, parameter['schema'])

    return Path(path=path, operations=operations)
Example #16
0
def _route_for_view(current_app, view, path=Path(), operations=set()):
    view_funcs = current_app.routes

    for uri, endpoint in iteritems(view_funcs):
        methods = set()
        for method, route_entry in iteritems(endpoint):
            method = method.lower()
            if route_entry.view_function == view and (not operations
                                                      or method in operations):
                if path.path and not path.path == uri:
                    break
                else:
                    methods.add(method)
        else:
            if methods:
                return uri, methods

    raise APISpecError(
        'Could not find endpoint for view {0} and path {1}'.format(
            view, getattr(path, 'path', None)))
Example #17
0
def path_from_urlspec(spec, route, operations, **kwargs):
    if not isinstance(route, ResourceRoute):
        raise Exception('Route is not ResourceRoute instance %s' % type(route))

    extensions = extensions_from_handler(route.handler)

    if operations is None:
        operations = {}
        for operation in operations_from_methods(route.handler, extensions):
            operations.update(operation)
        if not operations:
            raise APISpecError(
                'Could not find endpoint for route {0}'.format(route))

    if isinstance(route.resource, DynamicResource):
        path = route.get_info()['formatter']

    if isinstance(route.resource, PlainResource):
        path = route.get_info()['path']

    return Path(path=path, operations=operations)
Example #18
0
    def path_helper(self, rule=None, operations=None, **kwargs):
        """Get path from flask Rule and set path parameters in operations"""
        if rule is None:
            raise PluginMethodNotImplementedError

        for path_p in self.rule_to_params(rule):
            for operation in operations.values():
                parameters = operation.setdefault("parameters", [])
                # If a parameter with same name and location is already
                # documented, update. Otherwise, append as new parameter.
                p_doc = next((p for p in parameters if p["in"] == "path" and p["name"] == path_p["name"]), None)
                if p_doc is not None:
                    # If parameter already documented, mutate to update doc
                    # Ensure manual doc overwrites auto doc
                    p_doc.update({**path_p, **p_doc})
                else:
                    parameters.append(path_p)

        path = self.flaskpath2openapi(rule.rule)
        if APISPEC_VERSION_MAJOR == 0:
            return Path(path=path, operations=operations)
        return path
def path_helper(_spec, **kwargs):
    """Extracts swagger spec from `flask-restful` methods."""
    try:
        resource = kwargs.pop('resource')
    except KeyError:
        # Skip when resource isn't provided. This allows other extensions
        # to process this path.
        raise TypeError

    try:

        path = deduce_path(resource, **kwargs)

        # normalize path
        path = re.sub(r'<(?:[^:<>]+:)?([^<>]+)>', r'{\1}', path)

        operations = parse_operations(resource)

        return Path(path=path, operations=operations)
    except Exception as exc:
        logging.getLogger(__name__).exception("Exception parsing APISpec %s",
                                              exc)
        raise
Example #20
0
    def path_helper(self, rule, operations=None, **kwargs):
        """Get path from flask Rule and set path parameters in operations"""
        path = self.flaskpath2openapi(rule.rule)

        if operations:
            # Get path parameters
            path_parameters = self.rule_to_params(rule)
            if path_parameters:
                for operation in operations.values():
                    parameters = operation.setdefault('parameters', [])
                    # Add path parameters to documentation, updating if the name already exists
                    for path_p in path_parameters:
                        updated = False
                        for existing in parameters:
                            if getattr(existing, "name",
                                       None) == path_p["name"]:
                                existing = deepupdate(path_p, existing)
                                updated = True
                        if not updated:
                            parameters.append(path_p)

        if APISPEC_VERSION_MAJOR == 0:
            return Path(path=path, operations=operations)
        return path
Example #21
0
 def path_helper(self, path, **kwargs):
     if path.path == '/path_1':
         return Path(
             path='/path_1_modified',
             operations={'get': {'responses': {'200': {}}}},
         )
Example #22
0
 def path_helper(spec, view_func, **kwargs):
     return Path(path=view_func['path'])
Example #23
0
 def helper2(spec, eggs, **kwargs):
     return Path(path='/foo/bar')
Example #24
0
 def helper1(spec, spam, **kwargs):
     return Path(path='/foo/bar')
Example #25
0
 def test_add_path_strips_path_base_path(self, spec):
     spec.options['basePath'] = '/v1'
     path = Path(path='/v1/pets')
     spec.add_path(path)
     assert '/pets' in spec._paths
     assert '/v1/pets' not in spec._paths
Example #26
0
    def path_helper(self, view=None, **kwargs):
        """Path helper that allows passing a Schema as a response. Responses can be
        defined in a view's docstring.
        ::

            from pprint import pprint

            from my_app import Users, UserSchema

            class UserHandler:
                def get(self, user_id):
                    '''Get a user endpoint.
                    ---
                    description: Get a user
                    responses:
                        200:
                            description: A user
                            schema: UserSchema
                    '''
                    user = Users.get(id=user_id)
                    schema = UserSchema()
                    return schema.dumps(user)

            urlspec = (r'/users/{user_id}', UserHandler)
            spec.add_path(urlspec=urlspec)
            pprint(spec.to_dict()['paths'])
            # {'/users/{user_id}': {'get': {'description': 'Get a user',
            #                               'responses': {200: {'description': 'A user',
            #                                                   'schema': {'$ref': '#/definitions/User'}}}}}}

        ::

            from pprint import pprint

            from my_app import Users, UserSchema

            class UsersHandler:
                def get(self):
                    '''Get users endpoint.
                    ---
                    description: Get a list of users
                    responses:
                        200:
                            description: A list of user
                            schema:
                                type: array
                                items: UserSchema
                    '''
                    users = Users.all()
                    schema = UserSchema(many=True)
                    return schema.dumps(users)

            urlspec = (r'/users', UsersHandler)
            spec.add_path(urlspec=urlspec)
            pprint(spec.to_dict()['paths'])
            # {'/users': {'get': {'description': 'Get a list of users',
            #                     'responses': {200: {'description': 'A list of users',
            #                                         'schema': {'type': 'array',
            #                                                    'items': {'$ref': '#/definitions/User'}}}}}}}

        """
        operations = (kwargs.get('operations') or
                      (view
                       and utils.load_operations_from_docstring(view.__doc__)))
        if not operations:
            return None
        operations = operations.copy()
        return Path(operations=operations)
Example #27
0
 def path_helper(spec, view_func, **kwargs):
     return Path(path=view_func['path'], method='get')
Example #28
0
def resource_path_helper(spec, path, resource):
    """Provides path when given a FlaskRestful resource"""
    operations = utils.load_operations_from_docstring(resource.__doc__)
    return Path(path=path, operations=operations)
Example #29
0
def docstring_path_helper(spec, path, router, func, **kwargs):
    operations = load_operations_from_docstring(func.__doc__)

    cp_config = func._cp_config

    if operations is not None:
        for method, data in operations.items():

            if cp_config.get('tools.authentication.on', True):
                data['security'] = [{'Bearer': []}]

            if 'tools.model_in.cls' in cp_config:
                model_cls = cp_config['tools.model_in.cls']
                spec.definition(model_cls.__name__,
                                **parse_model(spec, model_cls))

                data['requestBody']['required'] = True
                data['requestBody']['content'] = {
                    'application/json': {
                        'schema': {
                            '$ref':
                            '#/components/schemas/' + model_cls.__name__
                        }
                    }
                }

            if 'tools.model_params.cls' in cp_config:
                model_cls = cp_config['tools.model_params.cls']
                data['parameters'] = data.get('parameters', [])

                # In query vs in path
                for key, obj in model_cls.__dict__.items():
                    inn = 'query'
                    if '{' + key + '}' in path.path:
                        inn = 'path'
                    if isinstance(obj, FieldDescriptor):
                        data['parameters'].append({
                            'name':
                            key,
                            'in':
                            inn,
                            'required':
                            model_cls._fields[key].required,
                            'schema':
                            parse_model_type(spec, model_cls._fields[key])
                        })

            if 'tools.model_out.cls' in cp_config:
                model_cls = cp_config['tools.model_out.cls']
                spec.definition(model_cls.__name__,
                                **parse_model(spec, model_cls))
                data['responses'][200]['content'] = {
                    'application/json': {
                        'schema': {
                            '$ref':
                            '#/components/schemas/' + model_cls.__name__
                        }
                    }
                }

            if 'tools.model_out_pagination.cls' in cp_config:
                model_cls = cp_config['tools.model_out_pagination.cls']
                spec.definition(model_cls.__name__,
                                **parse_model(spec, model_cls))
                data['responses'][200]['content'] = {
                    'application/json': {
                        'schema': {
                            'type': 'array',
                            'items': {
                                '$ref':
                                '#/components/schemas/' + model_cls.__name__
                            }
                        }
                    }
                }

            if isinstance(router, SandwichProjectRouter):
                data['parameters'] = data.get('parameters', [])
                data['parameters'].append({
                    'name': 'project_name',
                    'in': 'path',
                    'required': True,
                    'schema': {
                        'type': 'string'
                    }
                })

            if 'tools.enforce_permission.permission_name' in cp_config:
                data['x-required-permission'] = cp_config[
                    'tools.enforce_permission.permission_name']

    return Path(path=path.path, operations=operations)
    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}))