diff --git a/swh/web/api/apiresponse.py b/swh/web/api/apiresponse.py --- a/swh/web/api/apiresponse.py +++ b/swh/web/api/apiresponse.py @@ -5,8 +5,10 @@ import json import traceback +from typing import Any, Dict, Optional from django.utils.html import escape +from rest_framework.request import Request from rest_framework.response import Response from rest_framework.utils.encoders import JSONEncoder @@ -17,7 +19,7 @@ from swh.web.config import get_config -def compute_link_header(rv, options): +def compute_link_header(rv: Dict[str, Any], options: Dict[str, Any]) -> Dict[str, Any]: """Add Link header in returned value results. Args: @@ -55,7 +57,7 @@ return {} -def filter_by_fields(request, data): +def filter_by_fields(request: Request, data: Dict[str, Any]) -> Dict[str, Any]: """Extract a request parameter 'fields' if it exists to permit the filtering on the data dict's keys. @@ -64,13 +66,12 @@ """ fields = request.query_params.get("fields") if fields: - fields = set(fields.split(",")) - data = utils.filter_field_keys(data, fields) + data = utils.filter_field_keys(data, set(fields.split(","))) return data -def transform(rv): +def transform(rv: Dict[str, Any]) -> Dict[str, Any]: """Transform an eventual returned value with multiple layer of information with only what's necessary. @@ -90,7 +91,12 @@ return rv -def make_api_response(request, data, doc_data={}, options={}): +def make_api_response( + request: Request, + data: Dict[str, Any], + doc_data: Optional[Dict[str, Any]] = None, + options: Optional[Dict[str, Any]] = None, +) -> Response: """Generates an API response based on the requested mimetype. Args: @@ -103,18 +109,19 @@ a DRF Response a object """ + opts = options or {} if data: - options["headers"] = compute_link_header(data, options) + opts["headers"] = compute_link_header(data, opts) data = transform(data) data = filter_by_fields(request, data) - doc_env = doc_data + doc_env = doc_data or {} headers = {} - if "headers" in options: - doc_env["headers_data"] = options["headers"] - headers = options["headers"] + if "headers" in opts: + doc_env["headers_data"] = opts["headers"] + headers = opts["headers"] # get request status code - doc_env["status_code"] = options.get("status", 200) + doc_env["status_code"] = opts.get("status", 200) response_args = { "status": doc_env["status_code"], @@ -126,12 +133,12 @@ # documented views, we need to enrich the input data with documentation # related ones and inform DRF that we request HTML template rendering if request.accepted_media_type == "text/html": - + doc_env["response_data"] = data if data: - data = json.dumps( + doc_env["response_data"] = json.dumps( data, cls=JSONEncoder, sort_keys=True, indent=4, separators=(",", ": ") ) - doc_env["response_data"] = data + doc_env["heading"] = shorten_path(str(request.path)) # generate breadcrumbs data @@ -153,7 +160,9 @@ return Response(**response_args) -def error_response(request, error, doc_data): +def error_response( + request: Request, error: Exception, doc_data: Dict[str, Any] +) -> Response: """Private function to create a custom error response. Args: