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

42 statements  

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

1""" 

2Move a file in the safest way possible:: 

3 

4 >>> from django.core.files.move import file_move_safe 

5 >>> file_move_safe("/tmp/old_file", "/tmp/new_file") 

6""" 

7 

8import errno 

9import os 

10from shutil import copystat 

11 

12from django.core.files import locks 

13 

14__all__ = ["file_move_safe"] 

15 

16 

17def _samefile(src, dst): 

18 # Macintosh, Unix. 

19 if hasattr(os.path, "samefile"): 

20 try: 

21 return os.path.samefile(src, dst) 

22 except OSError: 

23 return False 

24 

25 # All other platforms: check for same pathname. 

26 return os.path.normcase(os.path.abspath(src)) == os.path.normcase( 

27 os.path.abspath(dst) 

28 ) 

29 

30 

31def file_move_safe( 

32 old_file_name, new_file_name, chunk_size=1024 * 64, allow_overwrite=False 

33): 

34 """ 

35 Move a file from one location to another in the safest way possible. 

36 

37 First, try ``os.rename``, which is simple but will break across filesystems. 

38 If that fails, stream manually from one file to another in pure Python. 

39 

40 If the destination file exists and ``allow_overwrite`` is ``False``, raise 

41 ``FileExistsError``. 

42 """ 

43 # There's no reason to move if we don't have to. 

44 if _samefile(old_file_name, new_file_name): 

45 return 

46 

47 try: 

48 if not allow_overwrite and os.access(new_file_name, os.F_OK): 

49 raise FileExistsError( 

50 "Destination file %s exists and allow_overwrite is False." 

51 % new_file_name 

52 ) 

53 

54 os.rename(old_file_name, new_file_name) 

55 return 

56 except OSError: 

57 # OSError happens with os.rename() if moving to another filesystem or 

58 # when moving opened files on certain operating systems. 

59 pass 

60 

61 # first open the old file, so that it won't go away 

62 with open(old_file_name, "rb") as old_file: 

63 # now open the new file, not forgetting allow_overwrite 

64 fd = os.open( 

65 new_file_name, 

66 ( 

67 os.O_WRONLY 

68 | os.O_CREAT 

69 | getattr(os, "O_BINARY", 0) 

70 | (os.O_EXCL if not allow_overwrite else 0) 

71 ), 

72 ) 

73 try: 

74 locks.lock(fd, locks.LOCK_EX) 

75 current_chunk = None 

76 while current_chunk != b"": 

77 current_chunk = old_file.read(chunk_size) 

78 os.write(fd, current_chunk) 

79 finally: 

80 locks.unlock(fd) 

81 os.close(fd) 

82 

83 try: 

84 copystat(old_file_name, new_file_name) 

85 except PermissionError as e: 

86 # Certain filesystems (e.g. CIFS) fail to copy the file's metadata if 

87 # the type of the destination filesystem isn't the same as the source 

88 # filesystem; ignore that. 

89 if e.errno != errno.EPERM: 

90 raise 

91 

92 try: 

93 os.remove(old_file_name) 

94 except PermissionError as e: 

95 # Certain operating systems (Cygwin and Windows) 

96 # fail when deleting opened files, ignore it. (For the 

97 # systems where this happens, temporary files will be auto-deleted 

98 # on close anyway.) 

99 if getattr(e, "winerror", 0) != 32: 

100 raise