Skip to content

Commit 6ecd197

Browse files
authored
gh-109503: Fix document for shutil.move() on usage of os.rename() since it's inaccurate (GH-109507)
Nonatomic move might be used even if the files are on the same filesystem in some cases.
1 parent 62a45fa commit 6ecd197

3 files changed

Lines changed: 19 additions & 8 deletions

File tree

Doc/library/shutil.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,14 @@ Directory and files operations
385385
If *dst* already exists but is not a directory, it may be overwritten
386386
depending on :func:`os.rename` semantics.
387387

388-
If the destination is on the current filesystem, then :func:`os.rename` is
389-
used. Otherwise, *src* is copied to the destination using *copy_function*
390-
and then removed. In case of symlinks, a new symlink pointing to the target
391-
of *src* will be created as the destination and *src* will be removed.
388+
:func:`os.rename` is preferably used internally when *src* and the destination are on
389+
the same filesystem. In case :func:`os.rename` fails due to :exc:`OSError`
390+
(e.g. the user has write permission to the destination file but not to its parent
391+
directory), this method falls back to using *copy_function*, in which case
392+
*src* is copied to the destination using *copy_function* and then removed.
393+
394+
In case of symlinks, a new symlink pointing to the target of *src* will be
395+
created in or as the destination, and *src* will be removed.
392396

393397
If *copy_function* is given, it must be a callable that takes two arguments,
394398
*src* and the destination, and will be used to copy *src* to the destination

Lib/shutil.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -885,10 +885,14 @@ def move(src, dst, copy_function=copy2):
885885
If dst already exists but is not a directory, it may be overwritten
886886
depending on os.rename() semantics.
887887
888-
If the destination is on our current filesystem, then rename() is used.
889-
Otherwise, src is copied to the destination and then removed. Symlinks are
890-
recreated under the new name if os.rename() fails because of cross
891-
filesystem renames.
888+
os.rename() is preferably used if the source and destination are on the
889+
same filesystem. In case os.rename() fails due to OSError (e.g. the user
890+
has write permission to *dst* file but not to its parent directory),
891+
this method falls back to using *copy_function* silently.
892+
Symlinks are also recreated under the new name if os.rename() fails
893+
because of cross filesystem renames.
894+
895+
It's recommended to use os.rename() if atomic move is strictly required.
892896
893897
The optional `copy_function` argument is a callable that will be used
894898
to copy the source or it will be delegated to `copytree`.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix documentation for :func:`shutil.move` on usage of
2+
:func:`os.rename` since nonatomic move might be used even if the files are
3+
on the same filesystem. Patch by Fang Li

0 commit comments

Comments
 (0)