Coverage for jutil/responses.py: 42%

39 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-07 16:40 -0500

1import mimetypes 

2import os 

3from typing import Any, List 

4from django.http import HttpResponse, FileResponse, Http404 

5from django.utils.translation import gettext as _ 

6from jutil.format import format_xml_file, format_xml_bytes, format_csv 

7 

8 

9class FileSystemFileResponse(FileResponse): 

10 """ 

11 File system download HTTP response. 

12 :param full_path: Full path to file 

13 :param filename: Filename (optional) passed to client. Defaults to basename of the full path. 

14 :param disposition: Content-Disposition, default attachment; filename=xxx 

15 """ 

16 

17 def __init__(self, full_path: str, filename: str = "", disposition: str = "", **kw): 

18 if not os.path.isfile(full_path): 

19 raise Http404(_("File {} not found").format(full_path)) 

20 if not filename: 

21 filename = os.path.basename(full_path) 

22 content_type = mimetypes.guess_type(filename)[0] 

23 super().__init__(open(full_path, "rb"), **kw) # pylint: disable=consider-using-with 

24 if content_type: 

25 self["Content-Type"] = content_type 

26 self["Content-Length"] = os.path.getsize(full_path) 

27 self["Content-Disposition"] = disposition if disposition else "attachment; filename={}".format(filename) 

28 

29 

30class CsvResponse(HttpResponse): 

31 """ 

32 CSV download HTTP response. 

33 """ 

34 

35 def __init__(self, rows: List[List[Any]], filename: str, dialect="excel", **kw): 

36 """ 

37 Returns CSV response. 

38 :param rows: List of column lists 

39 :param filename: Download response file name 

40 :param dialect: See csv.writer dialect 

41 :param kw: Parameters to be passed to HttpResponse __init__ 

42 """ 

43 buf = format_csv(rows, dialect=dialect).encode("utf-8") 

44 super().__init__(content=buf, content_type="text/csv", **kw) 

45 self["Content-Disposition"] = 'attachment;filename="{}"'.format(filename) 

46 

47 

48class FormattedXmlFileResponse(HttpResponse): 

49 def __init__(self, filename: str): 

50 content = format_xml_file(filename) 

51 super().__init__(content) 

52 self["Content-Type"] = "application/xml" 

53 self["Content-Length"] = len(content) 

54 self["Content-Disposition"] = "attachment; filename={}".format(os.path.basename(filename)) 

55 

56 

57class XmlResponse(HttpResponse): 

58 def __init__(self, content: bytes, filename: str): 

59 super().__init__(content) 

60 self["Content-Type"] = "application/xml" 

61 self["Content-Length"] = len(content) 

62 self["Content-Disposition"] = "attachment; filename={}".format(os.path.basename(filename)) 

63 

64 

65class FormattedXmlResponse(XmlResponse): 

66 def __init__(self, content: bytes, filename: str, encoding: str = "UTF-8", exceptions: bool = True): 

67 super().__init__(format_xml_bytes(content, encoding=encoding, exceptions=exceptions), filename)