json_response.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Copyright (c) 2018 Alexander Todorov <atodorov@MrSenko.com>
  2. # Licensed under the GPL 2.0: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  3. # For details: https://github.com/PyCQA/pylint-django/blob/master/LICENSE
  4. """
  5. Various suggestions about JSON http responses
  6. """
  7. import astroid
  8. from pylint import checkers, interfaces
  9. from pylint.checkers import utils
  10. from pylint_django.__pkginfo__ import BASE_ID
  11. class JsonResponseChecker(checkers.BaseChecker):
  12. """
  13. Looks for some common patterns when returning http responses containing
  14. JSON data!
  15. """
  16. __implements__ = (interfaces.IAstroidChecker,)
  17. # configuration section name
  18. name = "json-response-checker"
  19. msgs = {
  20. f"R{BASE_ID}01": (
  21. "Instead of HttpResponse(json.dumps(data)) use JsonResponse(data)",
  22. "http-response-with-json-dumps",
  23. "Used when json.dumps() is used as an argument to HttpResponse().",
  24. ),
  25. f"R{BASE_ID}02": (
  26. "Instead of HttpResponse(content_type='application/json') use JsonResponse()",
  27. "http-response-with-content-type-json",
  28. "Used when HttpResponse() is returning application/json.",
  29. ),
  30. f"R{BASE_ID}03": (
  31. "Redundant content_type parameter for JsonResponse()",
  32. "redundant-content-type-for-json-response",
  33. "Used when JsonResponse() contains content_type parameter. "
  34. "This is either redundant or the content_type is not JSON "
  35. "which is probably an error.",
  36. ),
  37. }
  38. @utils.check_messages(
  39. "http-response-with-json-dumps",
  40. "http-response-with-content-type-json",
  41. "redundant-content-type-for-json-response",
  42. )
  43. def visit_call(self, node):
  44. if (
  45. node.func.as_string().endswith("HttpResponse")
  46. and node.args
  47. and isinstance(node.args[0], astroid.Call)
  48. and node.args[0].func.as_string() == "json.dumps"
  49. ):
  50. self.add_message("http-response-with-json-dumps", node=node)
  51. if node.func.as_string().endswith("HttpResponse") and node.keywords:
  52. for keyword in node.keywords:
  53. if keyword.arg == "content_type" and keyword.value.as_string().lower().find("application/json") > -1:
  54. self.add_message("http-response-with-content-type-json", node=node)
  55. break
  56. if node.func.as_string().endswith("JsonResponse") and node.keywords:
  57. for keyword in node.keywords:
  58. if keyword.arg == "content_type":
  59. self.add_message("redundant-content-type-for-json-response", node=node)
  60. break