import functools import inspect from flask_apispec import doc from atlas_um.api.schemas import UnauthorizedSchema def dump_with(schema): """Helper decorator to dump func result with a schema.""" def decorator(func): @functools.wraps(func) def decorated_func(*args, **kwargs): result = func(*args, **kwargs) schema_instance = schema() if inspect.isclass(schema) else schema return schema_instance.dump(result) return decorated_func return decorator def _doc_extend_responses_schema(responses_schema, data): for key, value in data.items(): responses_schema[key] = { "description": value["description"], "content": { "application/json": { "schema": value["schema"], } }, } return responses_schema def _doc_get_unauthorized_response_schema(): return { "description": "Unauthorized", "content": { "application/json": { "schema": UnauthorizedSchema, } }, } def _doc_extend_params_with_path_params(params, path_params): for key, value in path_params.items(): params[key] = { "name": key, "in": "path", "description": value, "required": True, "schema": { "type": "string", }, } return params def doc_details_view( summary, description, tags, responses, path_params=None, **doc_kwargs ): def decorator(func): responses_schema = {} responses_schema = _doc_extend_responses_schema( responses_schema, responses ) responses_schema[401] = _doc_get_unauthorized_response_schema() params = doc_kwargs.pop("params", None) or {} if path_params: params = _doc_extend_params_with_path_params(params, path_params) @functools.wraps(func) @doc( summary=summary, description=description, tags=tags, responses=responses_schema, params=params, **doc_kwargs, ) def decorated_func(*args, **kwargs): return func(*args, **kwargs) return decorated_func return decorator def doc_list_view( summary, description, tags, responses, path_params=None, **doc_kwargs ): def decorator(func): responses_schema = {} responses_schema = _doc_extend_responses_schema( responses_schema, responses ) responses_schema[401] = _doc_get_unauthorized_response_schema() params = doc_kwargs.pop("params", None) or { "limit": { "name": "limit", "in": "query", "description": "Limit entities quantity", "required": False, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, }, }, "offset": { "name": "offset", "in": "query", "description": "Offset from the begining", "required": False, "schema": { "type": "integer", "minimum": 1, }, }, "order": { "name": "order", "in": "query", "description": "Order entities by fields", "required": False, "schema": { "type": "string", }, }, "filter": { "name": "filter", "in": "query", "description": "Filter entities by fields with " "`field_name1:value1,value_2;" "field_nameN:valueN` syntax", "required": False, "schema": { "type": "string", }, }, } if path_params: params = _doc_extend_params_with_path_params(params, path_params) @functools.wraps(func) @doc( summary=summary, description=description, tags=tags, params=params, responses=responses_schema, **doc_kwargs, ) def decorated_func(*args, **kwargs): return func(*args, **kwargs) return decorated_func return decorator