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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)