示例#1
0
    def swagger_doc_gen(func):
        """
            Decorator used to document relationship methods exposed in the API
        """

        parent_class = cls.relationship.parent.class_
        child_class = cls.relationship.mapper.class_
        class_name = cls.__name__
        http_method = func.__name__.lower()
        #######################################################################
        # Following will only happen when exposing an exisiting DB
        #
        if not getattr(parent_class, "object_id", None):
            parent_class._s_object_id = parent_class.__name__ + "Id"
        if not getattr(child_class, "object_id", None):
            child_class._s_object_id = child_class.__name__ + "Id"
        if not getattr(parent_class, "sample_id", None):
            setattr(parent_class, "sample_id", lambda: "")
        if not getattr(child_class, "sample_id", None):
            setattr(child_class, "sample_id", lambda: "")
        if not getattr(child_class, "get_swagger_doc", None):
            setattr(child_class, "get_swagger_doc", lambda x: (None, {}))
        #
        #######################################################################

        parameters = [
            {
                "name": parent_class._s_object_id,
                "in": "path",
                "type": "string",
                "default": parent_class._s_sample_id(),
                "description": "{} item".format(parent_class.__name__),
                "required": True,
            },
            {
                "name": child_class._s_object_id,
                "in": "path",
                "type": "string",
                "default": child_class._s_sample_id(),
                "description": "{} item".format(class_name),
                "required": True,
            },
        ]

        if tags is None:
            doc_tags = [cls._s_collection_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags}
        doc.update(parse_object_doc(func))

        responses = {}
        if http_method == "get":
            _, responses = cls._s_get_swagger_doc(http_method)
        elif http_method in ("post", "patch"):
            _, responses = cls._s_get_swagger_doc(http_method)
            child_sample_id = child_class._s_sample_id()

            _, responses = child_class._s_get_swagger_doc("patch")
            data = {"type": child_class._s_type, "id": child_sample_id}

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                data = [data]
            rel_post_schema = schema_from_object(
                "{}_Relationship".format(class_name), {"data": data})
            parameters.append({
                "name": "{} body".format(class_name),
                "in": "body",
                "description": "{} POST model".format(class_name),
                "schema": rel_post_schema,
                "required": True,
            })

        elif http_method == "delete":
            child_sample_id = child_class._s_sample_id()

            _, responses = child_class._s_get_swagger_doc("patch")
            data = {"type": child_class._s_type, "id": child_sample_id}

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                data = [data]
            rel_del_schema = schema_from_object(
                "{}_Relationship".format(class_name), {"data": data})
            parameters.append({
                "name": "{} body".format(class_name),
                "in": "body",
                "description": "{} POST model".format(class_name),
                "schema": rel_del_schema,
                "required": True,
            })

        else:
            # one of 'options', 'head', 'patch'
            safrs.log.info('no documentation for "{}" '.format(http_method))

        doc["parameters"] = parameters
        if doc.get("responses"):
            responses.update(
                {str(val): desc
                 for val, desc in doc["responses"].items()})

        if is_debug():
            responses.update(debug_responses)

        doc["responses"] = responses

        direction = "to-many" if cls.relationship.direction in (
            ONETOMANY, MANYTOMANY) else "to-one"
        parent_name = parent_class.__name__  # to be used by f-string
        child_name = child_class.__name__  # to be used by f-string
        apply_fstring(doc, locals())
        return swagger.doc(doc)(func)
示例#2
0
文件: swagger_doc.py 项目: maab/safrs
    def swagger_doc_gen(func):
        """
            decorator
        """
        method = getattr(cls, method_name, None)
        method_doc = parse_object_doc(method)
        class_name = cls.__name__
        if tags is None:
            doc_tags = [cls._s_collection_name]
        else:
            doc_tags = tags

        responses = method_doc.get(
            "responses",
            {HTTPStatus.OK.value: {
                "description": HTTPStatus.OK.description
            }})
        if is_debug():
            responses.update(debug_responses)

        summary = method_doc.get(
            "summary", "Invoke {}.{}".format(class_name, method_name))
        description = method_doc.get("description", summary)

        doc = {
            "tags": doc_tags,
            "description": description,
            "summary": summary,
            "responses": responses
        }

        model_name = "{}_{}_{}".format("Invoke ", class_name, method_name)
        param_model = SchemaClassFactory(model_name, {})
        parameters, fields, description, method = get_swagger_doc_arguments(
            cls, method_name, http_method=func.__name__)

        if func.__name__ == "get":
            if not parameters:
                parameters = [{
                    "name": "varargs",
                    "in": "query",
                    "description": "{} arguments".format(method_name),
                    "required": False,
                    "type": "string",
                }]
        else:
            # Retrieve the swagger schemas for the jsonapi_rpc methods from the docstring
            parameters, fields, description, method = get_swagger_doc_arguments(
                cls, method_name, http_method=func.__name__)
            model_name = "{}_{}_{}".format(func.__name__, cls.__name__,
                                           method_name)
            param_model = SchemaClassFactory(model_name, fields)

            parameters.append({
                "name": model_name,
                "in": "body",
                "description": description,
                "schema": param_model,
                "required": True
            })

        # URL Path Parameter
        default_id = cls._s_sample_id()
        parameters.append({
            "name": cls._s_object_id,
            "in": "path",
            "type": "string",
            "default": default_id,
            "required": True
        })  # parameter id, e.g. UserId
        doc["parameters"] = parameters
        doc["produces"] = ["application/vnd.api+json"]

        apply_fstring(doc, locals())
        return swagger.doc(doc)(func)
示例#3
0
    def swagger_doc_gen(func, instance=False):
        """
            Decorator used to document SAFRSRestAPI HTTP methods exposed in the API
        """
        default_id = cls._s_sample_id()
        class_name = cls.__name__
        collection_name = cls._s_collection_name
        http_method = func.__name__.lower()
        parameters = [
            {
                "name": cls._s_object_id,
                "in": "path",
                "type": "string",
                "default": default_id,
                "required": True,
            },  # parameter id, e.g. UserId
            {
                "name": "Content-Type",  # parameter id, e.g. UserId
                "in": "header",
                "type": "string",
                "default": "application/vnd.api+json",
                "enum": ["application/vnd.api+json", "application/json"],
                "required": True,
            },
        ]
        if tags is None:
            doc_tags = [collection_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags}

        responses = {}
        # adhere to open api
        # the model_name will hold the OAS "$ref" schema reference
        coll_model_name = "{}_{}_coll".format(
            class_name, http_method)  # collection model name
        inst_model_name = "{}_{}_inst".format(
            class_name, http_method)  # instance model name

        sample_dict = cls._s_sample_dict()

        # Samples with "id" are used for GET and PATCH
        coll_sample_data = schema_from_object(
            coll_model_name, {
                "data": [{
                    "attributes": sample_dict,
                    "type": cls._s_type,
                    "id": cls._s_sample_id()
                }]
            })

        inst_sample_data = schema_from_object(
            inst_model_name, {
                "data": {
                    "attributes": sample_dict,
                    "type": cls._s_type,
                    "id": cls._s_sample_id()
                }
            })

        cls.swagger_models["instance"] = inst_sample_data
        cls.swagger_models["collection"] = coll_sample_data

        if http_method == "get":
            doc["summary"] = "Retrieve a {} object".format(class_name)
            doc["collection_summary"] = "Retrieve a collection of {} objects".format(
                class_name)
            body, responses = cls._s_get_swagger_doc(http_method)
            responses[HTTPStatus.OK.value] = {"schema": coll_sample_data}

        elif http_method == "patch":
            post_model, responses = cls._s_get_swagger_doc(http_method)

            parameters.append({
                "name": "PATCH body",
                "in": "body",
                "description": "{} attributes".format(class_name),
                "schema": inst_sample_data,
                "required": True,
            })
        elif http_method == "post":
            _, responses = cls._s_get_swagger_doc(http_method)
            doc["summary"] = "Create a {} object".format(class_name)

            # Create the default POST body schema
            sample_dict = cls._s_sample_dict()
            # The POST sample doesn't contain an "id", unless cls.allow_client_generated_ids is True
            sample_data = schema_from_object(
                inst_model_name,
                {"data": {
                    "attributes": sample_dict,
                    "type": cls._s_type
                }})
            if cls.allow_client_generated_ids:
                sample_data = schema_from_object(
                    inst_model_name, {
                        "data": {
                            "attributes": sample_dict,
                            "type": cls._s_type,
                            "id": "client_generated"
                        }
                    })
            parameters.append({
                "name": "POST body",
                "in": "body",
                "description": "{} attributes".format(class_name),
                "schema": sample_data,
                "required": True,
            })

        elif http_method == "delete":
            _, responses = cls._s_get_swagger_doc(http_method)
        else:
            # one of 'options', 'head', 'delete'
            safrs.log.debug(
                'no additional documentation for "{}" '.format(func))

        if is_debug():
            responses.update(debug_responses)

        doc["parameters"] = parameters
        doc["responses"] = responses
        doc["produces"] = ["application/vnd.api+json"]

        method_doc = parse_object_doc(func)
        safrs.dict_merge(doc, method_doc)
        apply_fstring(doc, locals())
        return swagger.doc(doc)(func)
示例#4
0
    def swagger_doc_gen(func):
        '''
            Decorator used to document (SAFRSBase) class methods exposed in the API
        '''
        default_id = cls._s_sample_id()
        class_name = cls.__name__
        table_name = cls.__tablename__
        http_method = func.__name__.lower()
        parameters = [
            {
                'name': cls.object_id,  # parameter id, e.g. UserId
                'in': 'path',
                'type': 'string',
                'default': default_id,
                'required': True
            },
            {
                'name': 'Content-Type',  # parameter id, e.g. UserId
                'in': 'header',
                'type': 'string',
                'default': 'application/vnd.api+json',
                'required': True
            },
        ]
        if tags is None:
            doc_tags = [table_name]
        else:
            doc_tags = tags

        doc = {
            'tags': doc_tags,
            'description': 'Returns a {}'.format(class_name)
        }

        responses = {}
        # adhere to open api
        model_name = '{}_{}'.format(class_name, http_method)
        if http_method == 'get':
            doc['summary'] = 'Retrieve a {} object'.format(class_name)
            _, responses = cls.get_swagger_doc(http_method)

        elif http_method == 'post':
            _, responses = cls.get_swagger_doc(http_method)
            doc['summary'] = 'Create a {} object'.format(class_name)

            #
            # Create the default POST body schema
            #
            sample_dict = cls._s_sample_dict()
            sample_data = schema_from_object(
                model_name,
                {'data': {
                    'attributes': sample_dict,
                    'type': table_name
                }})
            parameters.append({
                'name': 'POST body',
                'in': 'body',
                'description': '{} attributes'.format(class_name),
                'schema': sample_data,
                'required': True
            })

        elif http_method == 'delete':
            doc['summary'] = doc['description'] = 'Delete a {} object'.format(
                class_name)
            responses = {
                '204': {
                    'description': 'Object Deleted'
                },
                '404': {
                    'description': 'Object Not Found'
                }
            }

        elif http_method == 'patch':
            doc['summary'] = 'Update a {} object'.format(class_name)
            post_model, responses = cls.get_swagger_doc('patch')
            sample = cls._s_sample_dict()
            sample_dict = cls._s_sample_dict()
            if sample:
                sample_data = schema_from_object(
                    model_name, {
                        'data': {
                            'attributes': sample_dict,
                            'id': cls._s_sample_id(),
                            'type': table_name
                        }
                    })
            else:
                sample_data = schema_from_object(
                    model_name, {
                        'data': {
                            'attributes': sample_dict,
                            'id': cls._s_sample_id(),
                            'type': table_name
                        }
                    })
            parameters.append({
                'name': 'POST body',
                'in': 'body',
                'description': '{} attributes'.format(class_name),
                'schema': sample_data,
                'required': True
            })
        else:
            # one of 'options', 'head', 'patch'
            safrs.LOGGER.debug('no documentation for "%s" ', http_method)

        responses_str = {}
        for k, v in responses.items():
            # convert int response code to string
            responses_str[str(k)] = v

        doc['parameters'] = parameters
        doc['responses'] = responses_str
        doc['produces'] = ["application/json"]

        method_doc = parse_object_doc(func)
        safrs.dict_merge(doc, method_doc)

        return swagger.doc(doc)(func)
示例#5
0
    def swagger_doc_gen(func):
        '''
            Decorator used to document relationship methods exposed in the API
        '''

        parent_class = cls.relationship.parent.class_
        child_class = cls.relationship.mapper.class_
        class_name = cls.__name__
        table_name = cls.__tablename__
        http_method = func.__name__.lower()
        #######################################################################
        # Following will only happen when exposing an exisiting DB
        #
        if not getattr(parent_class, 'object_id', None):
            parent_class.object_id = parent_class.__name__ + 'Id'
        if not getattr(child_class, 'object_id', None):
            child_class.object_id = child_class.__name__ + 'Id'
        if not getattr(parent_class, 'sample_id', None):
            setattr(parent_class, 'sample_id', lambda: '')
        if not getattr(child_class, 'sample_id', None):
            setattr(child_class, 'sample_id', lambda: '')
        if not getattr(child_class, 'get_swagger_doc', None):
            setattr(child_class, 'get_swagger_doc', lambda x: (None, {}))
        #
        #######################################################################

        parameters = [{
            'name': parent_class.object_id,
            'in': 'path',
            'type': 'string',
            'default': parent_class._s_sample_id(),
            'description': '{} item'.format(parent_class.__name__),
            'required': True
        }, {
            'name': child_class.object_id,
            'in': 'path',
            'type': 'string',
            'default': child_class._s_sample_id(),
            'description': '{} item'.format(class_name),
            'required': True
        }]

        parent_name = parent_class.__name__

        if tags is None:
            doc_tags = [table_name]
        else:
            doc_tags = tags

        doc = {
            'tags':
            doc_tags,
            'description':
            'Returns {} {} ids'.format(parent_name, cls.relationship.key),
        }

        responses = {}
        if http_method == 'get':
            doc['summary'] = 'Retrieve a {} object'.format(class_name)
            _, responses = cls.get_swagger_doc(http_method)
        elif http_method in ('post', 'patch'):
            _, responses = cls.get_swagger_doc(http_method)
            doc['summary'] = 'Update {}'.format(cls.relationship.key)
            doc['description'] = 'Add a {} object to the {} relation on {}'.format(
                child_class.__name__, cls.relationship.key, parent_name)
            sample_attrs = {}
            sample = getattr(cls, 'sample', lambda: None)()
            if sample:
                sample_attrs = sample._s_sample_dict()
                sample_id = sample.id

            child_sample_id = child_class._s_sample_id()

            _, responses = child_class.get_swagger_doc('patch')
            data = {
                'type': child_class.__tablename__,
                'attributes': sample_attrs,
                'id': child_sample_id
            }

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                data = [data]
            rel_post_schema = schema_from_object(
                '{}_Relationship'.format(class_name), {'data': data})
            parameters.append({
                'name': '{} body'.format(class_name),
                'in': 'body',
                'description': '{} POST model'.format(class_name),
                'schema': rel_post_schema,
                'required': True
            })

        elif http_method == 'delete':
            doc['summary'] = 'Delete from {} {}'.format(
                parent_name, cls.relationship.key)
            doc['description'] = 'Delete a {} object from the {} relation on {}'.format(
                child_class.__name__, cls.relationship.key, parent_name)
            responses = {'204': {'description': 'Object Deleted'}}

        else:
            # one of 'options', 'head', 'patch'
            safrs.LOGGER.info('no documentation for "%s" ', http_method)

        if http_method in ('patch', ):
            #put_model, responses = child_class.get_swagger_doc(http_method)
            doc['summary'] = 'Update a {} object'.format(class_name)
            responses = {'201': {'description': 'Object Updated'}}

        doc['parameters'] = parameters
        doc['responses'] = responses

        return swagger.doc(doc)(func)
示例#6
0
    def swagger_doc_gen(func):
        '''
            Decorator used to document (SAFRSBase) class methods exposed in the API
        '''

        default_id = cls.sample_id()
        class_name = cls.__name__
        table_name = cls.__tablename__
        http_method = func.__name__.lower()
        parameters = [{
            'name': cls.object_id,  # parameter id, e.g. UserId
            'in': 'path',
            'type': 'string',
            'default': default_id,
            'required': True
        }]

        if tags is None:
            doc_tags = [table_name]
        else:
            doc_tags = tags

        doc = {
            'tags': doc_tags,
            'description': 'Returns a {}'.format(class_name)
        }

        responses = {}

        # adhere to open api
        model_name = '{}_{}'.format(class_name, http_method)
        if http_method == 'get':
            doc['summary'] = 'Retrieve a {} object'.format(class_name)
            _, responses = cls.get_swagger_doc(http_method)

        elif http_method == 'post':
            _, responses = cls.get_swagger_doc(http_method)
            doc['summary'] = 'Create a {} object'.format(class_name)

            #
            # Create the default POST body schema
            #
            sample = cls.sample()
            if sample:
                sample_dict = get_sample_dict(sample)
                sample_data = schema_from_object(
                    model_name,
                    {'data': {
                        'attributes': sample_dict,
                        'type': class_name
                    }})
            elif cls.sample_id():
                sample_data = schema_from_object(
                    model_name, {
                        'data': {
                            'attributes':
                            {attr: ''
                             for attr in cls._s_jsonapi_attrs},
                            'type': class_name
                        }
                    })
            else:
                sample_data = {}

            parameters.append({
                'name': 'POST body',
                'in': 'body',
                'description': '{} attributes'.format(class_name),
                'schema': sample_data,
                'required': True
            })

        elif http_method == 'delete':
            doc['summary'] = doc['description'] = 'Delete a {} object'.format(
                class_name)
            responses = {
                '204': {
                    'description': 'Object Deleted'
                },
                '404': {
                    'description': 'Object Not Found'
                }
            }

        elif http_method == 'patch':
            doc['summary'] = 'Update a {} object'.format(class_name)
            post_model, responses = cls.get_swagger_doc('patch')
            sample = cls.sample()
            if sample:
                sample_dict = get_sample_dict(sample)
                sample_data = schema_from_object(
                    model_name, {
                        'data': {
                            'attributes': sample_dict,
                            'id': cls.sample_id(),
                            'type': class_name
                        }
                    })
            else:
                sample_data = schema_from_object(
                    model_name, {
                        'data': {
                            'attributes':
                            {attr: ''
                             for attr in cls._s_jsonapi_attrs},
                            'id': cls.sample_id(),
                            'type': class_name
                        }
                    })

            parameters.append({
                'name': 'POST body',
                'in': 'body',
                'description': '{} attributes'.format(class_name),
                'schema': sample_data,
                'required': True
            })
        else:
            # one of 'options', 'head', 'patch'
            log.debug('no documentation for "{}" '.format(http_method))

        doc['parameters'] = parameters
        doc['responses'] = responses
        doc["produces"] = ["application/json"]

        return swagger.doc(doc)(func)
示例#7
0
    def swagger_doc_gen(func):

        class_name = cls.__name__
        if tags is None:
            doc_tags = [class_name]
        else:
            doc_tags = tags

        doc = {
            'tags': doc_tags,
            'description': 'Invoke {}.{}'.format(class_name, method_name),
            'summary': 'Invoke {}.{}'.format(class_name, method_name)
        }

        model_name = '{}_{}_{}'.format('Invoke ', class_name, method_name)
        param_model = SchemaClassFactory(model_name, {})

        if func.__name__ == 'get':
            parameters = [{
                'name': 'varargs',
                'in': 'query',
                'description': '{} arguments'.format(method_name),
                'required': False,
                'type': 'string'
            }]
        else:
            # typically POST
            parameters, fields, description, method = get_swagger_doc_post_arguments(
                cls, method_name)
            '''if inspect.ismethod(method) and method.__self__ is cls:
                # Mark classmethods: only these can be called when no {id} is given as parameter
                # in the swagger ui
                description += ' (classmethod)' '''

            #
            # Retrieve the swagger schemas for the documented_api_methods
            #
            model_name = '{}_{}_{}'.format(func.__name__, cls.__name__,
                                           method_name)
            param_model = SchemaClassFactory(model_name, fields)
            parameters.append({
                'name': model_name,
                'in': 'body',
                'description': description,
                'schema': param_model,
                'required': True
            })

        # URL Path Parameter
        default_id = cls._s_sample_id()
        parameters.append({
            'name': cls.object_id,  # parameter id, e.g. UserId
            'in': 'path',
            'type': 'string',
            'default': default_id,
            'required': True
        })
        doc['parameters'] = parameters
        doc["produces"] = ["application/json"]
        doc['responses'] = responses = {'200': {'description': 'Success'}}

        return swagger.doc(doc)(func)
示例#8
0
    def swagger_doc_gen(func):
        """
        Decorator used to document relationship methods exposed in the API
        """

        parent_class = cls.relationship.parent.class_
        child_class = cls.relationship.mapper.class_
        class_name = cls.__name__
        http_method = func.__name__.lower()
        #######################################################################
        # Following will only happen when exposing an exisiting DB
        #
        if not getattr(parent_class, "object_id", None):
            parent_class._s_object_id = parent_class.__name__ + "Id"
        if not getattr(child_class, "object_id", None):
            child_class._s_object_id = child_class.__name__ + "Id"
        if not getattr(parent_class, "sample_id", None):
            setattr(parent_class, "sample_id", lambda: "")
        if not getattr(child_class, "sample_id", None):
            setattr(child_class, "sample_id", lambda: "")
        if not getattr(child_class, "get_swagger_doc", None):
            setattr(child_class, "get_swagger_doc", lambda x: (None, {}))
        #
        #######################################################################

        parameters = [
            {
                "name": parent_class._s_object_id,
                "in": "path",
                "type": "string",
                "default": parent_class._s_sample_id(),
                "description": f"{parent_class.__name__} item",
                "required": True,
            },
            {
                "name": child_class._s_object_id,
                "in": "path",
                "type": "string",
                "default": child_class._s_sample_id(),
                "description": f"{class_name} item",
                "required": True,
            },
        ]

        if tags is None:
            doc_tags = [cls._s_collection_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags}
        doc.update(parse_object_doc(func))

        responses = {}

        # Shema names (for the swagger "references")
        model_name = f"{class_name}_rel_inst"  # instance model name
        if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
            model_name = f"{class_name}_rel_coll"  # collection model name

        if http_method == "get":
            _, responses = cls._s_get_swagger_doc(http_method)
        elif http_method in ("post", "patch"):
            _, responses = cls._s_get_swagger_doc(http_method)
            child_sample_id = child_class._s_sample_id()

            _, responses = child_class._s_get_swagger_doc("patch")
            data = {"type": child_class._s_type, "id": child_sample_id}

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                # tomany relationships only return a 204 accepted
                data = [data]
                responses.pop(HTTPStatus.OK.value, None)

            rel_post_schema = schema_from_object(model_name, {"data": data})
            rel_post_schema.description += f"{class_name} {http_method} relationship;"
            cls.swagger_models["instance"] = rel_post_schema
            cls.swagger_models["collection"] = rel_post_schema
            parameters.append({
                "name": f"{class_name} body",
                "in": "body",
                "description": f"{class_name} POST model",
                "schema": rel_post_schema,
                "required": True,
            })

            if cls.relationship.direction is MANYTOONE:
                # toone relationships return 200 OK
                responses[HTTPStatus.OK.value] = {
                    "schema": rel_post_schema,
                    "description": HTTPStatus.OK.description
                }

        elif http_method == "delete":
            child_sample_id = child_class._s_sample_id()

            _, responses = child_class._s_get_swagger_doc("patch")
            data = {"type": child_class._s_type, "id": child_sample_id}

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                data = [data]
            rel_del_schema = schema_from_object(model_name, {"data": data})
            parameters.append({
                "name": f"{class_name} body",
                "in": "body",
                "description": f"{class_name} POST model",
                "schema": rel_del_schema,
                "required": True,
            })

        elif http_method != "options":
            # one of 'options', 'head', 'patch'
            safrs.log.info(f'no documentation for "{http_method}" ')

        doc["parameters"] = parameters
        if doc.get("responses"):
            responses.update(
                {str(val): desc
                 for val, desc in doc["responses"].items()})

        if is_debug():
            responses.update(debug_responses)

        doc["responses"] = responses

        parent_name = parent_class.__name__  # referenced by f-string in the jsonapi.py method docstring
        child_name = child_class.__name__  # referenced by f-string
        direction = "to-many" if cls.relationship.direction in (
            ONETOMANY, MANYTOMANY) else "to-one"
        apply_fstring(doc, locals())
        update_response_schema(doc["responses"])

        return swagger.doc(doc)(func)
示例#9
0
    def swagger_doc_gen(func):
        """
            Decorator used to document SAFRSRestAPI HTTP methods exposed in the API
        """
        default_id = cls._s_sample_id()
        class_name = cls.__name__
        collection_name = cls._s_collection_name
        http_method = func.__name__.lower()
        parameters = [
            {
                "name": cls.object_id,
                "in": "path",
                "type": "string",
                "default": default_id,
                "required": True
            },  # parameter id, e.g. UserId
            {
                "name": "Content-Type",  # parameter id, e.g. UserId
                "in": "header",
                "type": "string",
                "default": "application/vnd.api+json",
                "enum": ["application/vnd.api+json", "application/json"],
                "required": True,
            },
        ]
        if tags is None:
            doc_tags = [collection_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags}

        responses = {}
        # adhere to open api
        model_name = "{}_{}".format(class_name, http_method)
        if http_method == "get":
            doc["summary"] = "Retrieve a {} object".format(class_name)
            doc["collection_summary"] = "Retrieve a collection of {} objects".format(
                class_name)
            _, responses = cls.get_swagger_doc(http_method)

        elif http_method == "post":
            _, responses = cls.get_swagger_doc(http_method)
            doc["summary"] = "Create a {} object".format(class_name)

            # Create the default POST body schema
            sample_dict = cls._s_sample_dict()
            sample_data = schema_from_object(
                model_name,
                {"data": {
                    "attributes": sample_dict,
                    "type": cls._s_type
                }})
            parameters.append({
                "name": "POST body",
                "in": "body",
                "description": "{} attributes".format(class_name),
                "schema": sample_data,
                "required": True,
            })

        elif http_method == "patch":
            post_model, responses = cls.get_swagger_doc("patch")
            sample = cls._s_sample_dict()
            sample_dict = cls._s_sample_dict()
            if sample:
                sample_data = schema_from_object(
                    model_name, {
                        "data": [{
                            "attributes": sample_dict,
                            "id": cls._s_sample_id(),
                            "type": cls._s_type
                        }]
                    })
            else:
                sample_data = schema_from_object(
                    model_name, {
                        "data": {
                            "attributes": sample_dict,
                            "id": cls._s_sample_id(),
                            "type": cls._s_type
                        }
                    })
            parameters.append({
                "name": "PATCH body",
                "in": "body",
                "description": "{} attributes".format(class_name),
                "schema": sample_data,
                "required": True,
            })
        elif http_method == "delete":
            pass
        else:
            # one of 'options', 'head', 'delete'
            safrs.log.debug('no additional documentation for "%s" ', func)

        doc["parameters"] = parameters
        doc["responses"] = responses
        doc["produces"] = ["application/vnd.api+json"]

        method_doc = parse_object_doc(func)
        safrs.dict_merge(doc, method_doc)
        apply_fstring(doc, locals())
        return swagger.doc(doc)(func)
示例#10
0
    def swagger_doc_gen(func):
        """
            Decorator used to document relationship methods exposed in the API
        """

        parent_class = cls.relationship.parent.class_
        child_class = cls.relationship.mapper.class_
        class_name = cls.__name__
        table_name = cls.__tablename__
        http_method = func.__name__.lower()
        #######################################################################
        # Following will only happen when exposing an exisiting DB
        #
        if not getattr(parent_class, "object_id", None):
            parent_class.object_id = parent_class.__name__ + "Id"
        if not getattr(child_class, "object_id", None):
            child_class.object_id = child_class.__name__ + "Id"
        if not getattr(parent_class, "sample_id", None):
            setattr(parent_class, "sample_id", lambda: "")
        if not getattr(child_class, "sample_id", None):
            setattr(child_class, "sample_id", lambda: "")
        if not getattr(child_class, "get_swagger_doc", None):
            setattr(child_class, "get_swagger_doc", lambda x: (None, {}))
        #
        #######################################################################

        parameters = [
            {
                "name": parent_class.object_id,
                "in": "path",
                "type": "string",
                "default": parent_class._s_sample_id(),
                "description": "{} item".format(parent_class.__name__),
                "required": True,
            },
            {
                "name": child_class.object_id,
                "in": "path",
                "type": "string",
                "default": child_class._s_sample_id(),
                "description": "{} item".format(class_name),
                "required": True,
            },
        ]

        parent_name = parent_class.__name__

        if tags is None:
            doc_tags = [table_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags, "description": "Returns {} {} ids".format(parent_name, cls.relationship.key)}

        responses = {}
        if http_method == "get":
            doc["summary"] = "Retrieve a {} object".format(class_name)
            _, responses = cls.get_swagger_doc(http_method)
        elif http_method in ("post", "patch"):
            _, responses = cls.get_swagger_doc(http_method)
            doc["summary"] = "Update {}".format(cls.relationship.key)
            doc["description"] = "Add a {} object to the {} relation on {}".format(
                child_class.__name__, cls.relationship.key, parent_name
            )
            sample_attrs = {}
            sample = getattr(cls, "sample", lambda: None)()
            if sample:
                sample_attrs = sample._s_sample_dict()
                sample_id = sample.id

            child_sample_id = child_class._s_sample_id()

            _, responses = child_class.get_swagger_doc("patch")
            data = {"type": child_class.__tablename__, "attributes": sample_attrs, "id": child_sample_id}

            if cls.relationship.direction in (ONETOMANY, MANYTOMANY):
                data = [data]
            rel_post_schema = schema_from_object("{}_Relationship".format(class_name), {"data": data})
            parameters.append(
                {
                    "name": "{} body".format(class_name),
                    "in": "body",
                    "description": "{} POST model".format(class_name),
                    "schema": rel_post_schema,
                    "required": True,
                }
            )

        elif http_method == "delete":
            doc["summary"] = "Delete from {} {}".format(parent_name, cls.relationship.key)
            doc["description"] = "Delete a {} object from the {} relation on {}".format(
                child_class.__name__, cls.relationship.key, parent_name
            )
            responses = {"204": {"description": "Object Deleted"}}

        else:
            # one of 'options', 'head', 'patch'
            safrs.log.info('no documentation for "%s" ', http_method)

        if http_method in ("patch",):
            # put_model, responses = child_class.get_swagger_doc(http_method)
            doc["summary"] = "Update a {} object".format(class_name)
            responses = {"201": {"description": "Object Updated"}}

        doc["parameters"] = parameters
        doc["responses"] = responses

        return swagger.doc(doc)(func)
示例#11
0
    def swagger_doc_gen(func):
        """
            Decorator used to document (SAFRSBase) class methods exposed in the API
        """
        default_id = cls._s_sample_id()
        class_name = cls.__name__
        table_name = cls.__tablename__
        http_method = func.__name__.lower()
        parameters = [
            {
                "name": cls.object_id,  # parameter id, e.g. UserId
                "in": "path",
                "type": "string",
                "default": default_id,
                "required": True,
            },
            {
                "name": "Content-Type",  # parameter id, e.g. UserId
                "in": "header",
                "type": "string",
                "default": "application/vnd.api+json",
                "required": True,
            },
        ]
        if tags is None:
            doc_tags = [table_name]
        else:
            doc_tags = tags

        doc = {"tags": doc_tags, "description": "Returns a {}".format(class_name)}

        responses = {}
        # adhere to open api
        model_name = "{}_{}".format(class_name, http_method)
        if http_method == "get":
            doc["summary"] = "Retrieve a {} object".format(class_name)
            _, responses = cls.get_swagger_doc(http_method)

        elif http_method == "post":
            _, responses = cls.get_swagger_doc(http_method)
            doc["summary"] = "Create a {} object".format(class_name)

            #
            # Create the default POST body schema
            #
            sample_dict = cls._s_sample_dict()
            sample_data = schema_from_object(model_name, {"data": {"attributes": sample_dict, "type": table_name}})
            parameters.append(
                {
                    "name": "POST body",
                    "in": "body",
                    "description": "{} attributes".format(class_name),
                    "schema": sample_data,
                    "required": True,
                }
            )

        elif http_method == "delete":
            doc["summary"] = doc["description"] = "Delete a {} object".format(class_name)
            responses = {"204": {"description": "Object Deleted"}, "404": {"description": "Object Not Found"}}

        elif http_method == "patch":
            doc["summary"] = "Update a {} object".format(class_name)
            post_model, responses = cls.get_swagger_doc("patch")
            sample = cls._s_sample_dict()
            sample_dict = cls._s_sample_dict()
            if sample:
                sample_data = schema_from_object(
                    model_name, {"data": {"attributes": sample_dict, "id": cls._s_sample_id(), "type": table_name}}
                )
            else:
                sample_data = schema_from_object(
                    model_name, {"data": {"attributes": sample_dict, "id": cls._s_sample_id(), "type": table_name}}
                )
            parameters.append(
                {
                    "name": "POST body",
                    "in": "body",
                    "description": "{} attributes".format(class_name),
                    "schema": sample_data,
                    "required": True,
                }
            )
        else:
            # one of 'options', 'head', 'patch'
            safrs.log.debug('no documentation for "%s" ', http_method)

        responses_str = {}
        for k, v in responses.items():
            # convert int response code to string
            responses_str[str(k)] = v

        doc["parameters"] = parameters
        doc["responses"] = responses_str
        doc["produces"] = ["application/json"]

        method_doc = parse_object_doc(func)
        safrs.dict_merge(doc, method_doc)

        return swagger.doc(doc)(func)
示例#12
0
    def swagger_doc_gen(func):

        class_name = cls.__name__
        if tags is None:
            doc_tags = [class_name]
        else:
            doc_tags = tags

        doc = {
            "tags": doc_tags,
            "description": "Invoke {}.{}".format(class_name, method_name),
            "summary": "Invoke {}.{}".format(class_name, method_name),
        }

        model_name = "{}_{}_{}".format("Invoke ", class_name, method_name)
        param_model = SchemaClassFactory(model_name, {})
        parameters, fields, description, method = get_swagger_doc_arguments(cls, method_name, http_method=func.__name__)

        if func.__name__ == "get":
            if not parameters:
                parameters = [
                    {
                        "name": "varargs",
                        "in": "query",
                        "description": "{} arguments".format(method_name),
                        "required": False,
                        "type": "string",
                    }
                ]
            '''
            parameters.append(
                {"name": model_name, "in": "query", "description": description, "schema": param_model, "required": True}
            )'''
            

        else:
            #
            # Retrieve the swagger schemas for the jsonapi_rpc methods
            #
            parameters, fields, description, method = get_swagger_doc_arguments(cls, method_name, http_method=func.__name__)
            model_name = "{}_{}_{}".format(func.__name__, cls.__name__, method_name)
            param_model = SchemaClassFactory(model_name, fields)

            parameters.append(
                {"name": model_name, "in": "body", "description": description, "schema": param_model, "required": True}
            )

        # URL Path Parameter
        default_id = cls._s_sample_id()
        parameters.append(
            {
                "name": cls.object_id,  # parameter id, e.g. UserId
                "in": "path",
                "type": "string",
                "default": default_id,
                "required": True,
            }
        )
        doc["parameters"] = parameters
        doc["produces"] = ["application/json"]
        doc["responses"] = responses = {"200": {"description": "Success"}}

        return swagger.doc(doc)(func)