https://github.com/python/cpython/commit/855839685dbd4b0376cdfa36df0b6c93164334c1 commit: 855839685dbd4b0376cdfa36df0b6c93164334c1 branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-06-09T16:06:44+03:00 summary:
[3.14] gh-109503: Fix document for shutil.move() on usage of os.rename() since it's inaccurate (GH-109507) (GH-150612) Nonatomic move might be used even if the files are on the same filesystem in some cases. (cherry picked from commit 6ecd197c03c43412fc400235949fd8297f142e89) Co-authored-by: Fang Li <[email protected]> files: A Misc/NEWS.d/next/Documentation/2023-09-16-23-42-27.gh-issue-109503.mZ-kdU.rst M Doc/library/shutil.rst M Lib/shutil.py diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 9cdee8c4051d19b..d802a2572871eaf 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -388,10 +388,14 @@ Directory and files operations If *dst* already exists but is not a directory, it may be overwritten depending on :func:`os.rename` semantics. - If the destination is on the current filesystem, then :func:`os.rename` is - used. Otherwise, *src* is copied to the destination using *copy_function* - and then removed. In case of symlinks, a new symlink pointing to the target - of *src* will be created as the destination and *src* will be removed. + :func:`os.rename` is preferably used internally when *src* and the destination are on + the same filesystem. In case :func:`os.rename` fails due to :exc:`OSError` + (e.g. the user has write permission to the destination file but not to its parent + directory), this method falls back to using *copy_function*, in which case + *src* is copied to the destination using *copy_function* and then removed. + + In case of symlinks, a new symlink pointing to the target of *src* will be + created in or as the destination, and *src* will be removed. If *copy_function* is given, it must be a callable that takes two arguments, *src* and the destination, and will be used to copy *src* to the destination diff --git a/Lib/shutil.py b/Lib/shutil.py index 94f273ce88b4c31..a3a112f69541ef3 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -885,10 +885,14 @@ def move(src, dst, copy_function=copy2): If dst already exists but is not a directory, it may be overwritten depending on os.rename() semantics. - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. Symlinks are - recreated under the new name if os.rename() fails because of cross - filesystem renames. + os.rename() is preferably used if the source and destination are on the + same filesystem. In case os.rename() fails due to OSError (e.g. the user + has write permission to *dst* file but not to its parent directory), + this method falls back to using *copy_function* silently. + Symlinks are also recreated under the new name if os.rename() fails + because of cross filesystem renames. + + It's recommended to use os.rename() if atomic move is strictly required. The optional `copy_function` argument is a callable that will be used to copy the source or it will be delegated to `copytree`. diff --git a/Misc/NEWS.d/next/Documentation/2023-09-16-23-42-27.gh-issue-109503.mZ-kdU.rst b/Misc/NEWS.d/next/Documentation/2023-09-16-23-42-27.gh-issue-109503.mZ-kdU.rst new file mode 100644 index 000000000000000..c3c6c57569c2ea5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-09-16-23-42-27.gh-issue-109503.mZ-kdU.rst @@ -0,0 +1,3 @@ +Fix documentation for :func:`shutil.move` on usage of +:func:`os.rename` since nonatomic move might be used even if the files are +on the same filesystem. Patch by Fang Li _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
