Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/core/files/uploadedfile.py: 72%

59 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2Classes representing uploaded files. 

3""" 

4 

5import os 

6from io import BytesIO 

7 

8from django.conf import settings 

9from django.core.files import temp as tempfile 

10from django.core.files.base import File 

11from django.core.files.utils import validate_file_name 

12 

13__all__ = ( 

14 "UploadedFile", 

15 "TemporaryUploadedFile", 

16 "InMemoryUploadedFile", 

17 "SimpleUploadedFile", 

18) 

19 

20 

21class UploadedFile(File): 

22 """ 

23 An abstract uploaded file (``TemporaryUploadedFile`` and 

24 ``InMemoryUploadedFile`` are the built-in concrete subclasses). 

25 

26 An ``UploadedFile`` object behaves somewhat like a file object and 

27 represents some file data that the user submitted with a form. 

28 """ 

29 

30 def __init__( 

31 self, 

32 file=None, 

33 name=None, 

34 content_type=None, 

35 size=None, 

36 charset=None, 

37 content_type_extra=None, 

38 ): 

39 super().__init__(file, name) 

40 self.size = size 

41 self.content_type = content_type 

42 self.charset = charset 

43 self.content_type_extra = content_type_extra 

44 

45 def __repr__(self): 

46 return "<%s: %s (%s)>" % (self.__class__.__name__, self.name, self.content_type) 

47 

48 def _get_name(self): 

49 return self._name 

50 

51 def _set_name(self, name): 

52 # Sanitize the file name so that it can't be dangerous. 

53 if name is not None: 53 ↛ 65line 53 didn't jump to line 65, because the condition on line 53 was never false

54 # Just use the basename of the file -- anything else is dangerous. 

55 name = os.path.basename(name) 

56 

57 # File names longer than 255 characters can cause problems on older OSes. 

58 if len(name) > 255: 58 ↛ 59line 58 didn't jump to line 59, because the condition on line 58 was never true

59 name, ext = os.path.splitext(name) 

60 ext = ext[:255] 

61 name = name[: 255 - len(ext)] + ext 

62 

63 name = validate_file_name(name) 

64 

65 self._name = name 

66 

67 name = property(_get_name, _set_name) 

68 

69 

70class TemporaryUploadedFile(UploadedFile): 

71 """ 

72 A file uploaded to a temporary location (i.e. stream-to-disk). 

73 """ 

74 

75 def __init__(self, name, content_type, size, charset, content_type_extra=None): 

76 _, ext = os.path.splitext(name) 

77 file = tempfile.NamedTemporaryFile( 

78 suffix=".upload" + ext, dir=settings.FILE_UPLOAD_TEMP_DIR 

79 ) 

80 super().__init__(file, name, content_type, size, charset, content_type_extra) 

81 

82 def temporary_file_path(self): 

83 """Return the full path of this file.""" 

84 return self.file.name 

85 

86 def close(self): 

87 try: 

88 return self.file.close() 

89 except FileNotFoundError: 

90 # The file was moved or deleted before the tempfile could unlink 

91 # it. Still sets self.file.close_called and calls 

92 # self.file.file.close() before the exception. 

93 pass 

94 

95 

96class InMemoryUploadedFile(UploadedFile): 

97 """ 

98 A file uploaded into memory (i.e. stream-to-memory). 

99 """ 

100 

101 def __init__( 

102 self, 

103 file, 

104 field_name, 

105 name, 

106 content_type, 

107 size, 

108 charset, 

109 content_type_extra=None, 

110 ): 

111 super().__init__(file, name, content_type, size, charset, content_type_extra) 

112 self.field_name = field_name 

113 

114 def open(self, mode=None): 

115 self.file.seek(0) 

116 return self 

117 

118 def chunks(self, chunk_size=None): 

119 self.file.seek(0) 

120 yield self.read() 

121 

122 def multiple_chunks(self, chunk_size=None): 

123 # Since it's in memory, we'll never have multiple chunks. 

124 return False 

125 

126 

127class SimpleUploadedFile(InMemoryUploadedFile): 

128 """ 

129 A simple representation of a file, which just has content, size, and a name. 

130 """ 

131 

132 def __init__(self, name, content, content_type="text/plain"): 

133 content = content or b"" 

134 super().__init__( 

135 BytesIO(content), None, name, content_type, len(content), None, None 

136 ) 

137 

138 @classmethod 

139 def from_dict(cls, file_dict): 

140 """ 

141 Create a SimpleUploadedFile object from a dictionary with keys: 

142 - filename 

143 - content-type 

144 - content 

145 """ 

146 return cls( 

147 file_dict["filename"], 

148 file_dict["content"], 

149 file_dict.get("content-type", "text/plain"), 

150 )