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
« 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::
4 >>> from django.core.files.move import file_move_safe
5 >>> file_move_safe("/tmp/old_file", "/tmp/new_file")
6"""
8import errno
9import os
10from shutil import copystat
12from django.core.files import locks
14__all__ = ["file_move_safe"]
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
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 )
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.
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.
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
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 )
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
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)
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
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