diff options
author | shadchin <shadchin@yandex-team.com> | 2024-02-07 09:25:06 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.com> | 2024-02-07 09:40:03 +0300 |
commit | 3139d9ab6df2a7014d19b87582466d17b4f496e2 (patch) | |
tree | 7fcb26a72dac212aa26beaaa7cd769fb1e396b5e /contrib/tools/python3/src/Lib/shutil.py | |
parent | 4c04a8d1e278e6ca7ff16c11b74b2f16fc144253 (diff) | |
download | ydb-3139d9ab6df2a7014d19b87582466d17b4f496e2.tar.gz |
Update Python 3 to 3.11.8
Diffstat (limited to 'contrib/tools/python3/src/Lib/shutil.py')
-rw-r--r-- | contrib/tools/python3/src/Lib/shutil.py | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/contrib/tools/python3/src/Lib/shutil.py b/contrib/tools/python3/src/Lib/shutil.py index d108986d13..79b38cf456 100644 --- a/contrib/tools/python3/src/Lib/shutil.py +++ b/contrib/tools/python3/src/Lib/shutil.py @@ -298,11 +298,15 @@ def copymode(src, dst, *, follow_symlinks=True): sys.audit("shutil.copymode", src, dst) if not follow_symlinks and _islink(src) and os.path.islink(dst): - if hasattr(os, 'lchmod'): + if os.name == 'nt': + stat_func, chmod_func = os.lstat, os.chmod + elif hasattr(os, 'lchmod'): stat_func, chmod_func = os.lstat, os.lchmod else: return else: + if os.name == 'nt' and os.path.islink(dst): + dst = os.path.realpath(dst, strict=True) stat_func, chmod_func = _stat, os.chmod st = stat_func(src) @@ -378,8 +382,16 @@ def copystat(src, dst, *, follow_symlinks=True): # We must copy extended attributes before the file is (potentially) # chmod()'ed read-only, otherwise setxattr() will error with -EACCES. _copyxattr(src, dst, follow_symlinks=follow) + _chmod = lookup("chmod") + if os.name == 'nt': + if follow: + if os.path.islink(dst): + dst = os.path.realpath(dst, strict=True) + else: + def _chmod(*args, **kwargs): + os.chmod(*args) try: - lookup("chmod")(dst, mode, follow_symlinks=follow) + _chmod(dst, mode, follow_symlinks=follow) except NotImplementedError: # if we got a NotImplementedError, it's because # * follow_symlinks=False, @@ -660,7 +672,12 @@ def _rmtree_safe_fd(topfd, path, onerror): _rmtree_safe_fd(dirfd, fullname, onerror) try: os.close(dirfd) + except OSError: + # close() should not be retried after an error. dirfd_closed = True + onerror(os.close, fullname, sys.exc_info()) + dirfd_closed = True + try: os.rmdir(entry.name, dir_fd=topfd) except OSError: onerror(os.rmdir, fullname, sys.exc_info()) @@ -675,7 +692,10 @@ def _rmtree_safe_fd(topfd, path, onerror): onerror(os.path.islink, fullname, sys.exc_info()) finally: if not dirfd_closed: - os.close(dirfd) + try: + os.close(dirfd) + except OSError: + onerror(os.close, fullname, sys.exc_info()) else: try: os.unlink(entry.name, dir_fd=topfd) @@ -732,7 +752,12 @@ def rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None): _rmtree_safe_fd(fd, path, onerror) try: os.close(fd) + except OSError: + # close() should not be retried after an error. fd_closed = True + onerror(os.close, path, sys.exc_info()) + fd_closed = True + try: os.rmdir(path, dir_fd=dir_fd) except OSError: onerror(os.rmdir, path, sys.exc_info()) @@ -744,7 +769,10 @@ def rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None): onerror(os.path.islink, path, sys.exc_info()) finally: if not fd_closed: - os.close(fd) + try: + os.close(fd) + except OSError: + onerror(os.close, path, sys.exc_info()) else: if dir_fd is not None: raise NotImplementedError("dir_fd unavailable on this platform") @@ -785,12 +813,12 @@ def move(src, dst, copy_function=copy2): similar to the Unix "mv" command. Return the file or directory's destination. - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. + If dst is an existing directory or a symlink to a directory, then src is + moved inside that directory. The destination path in that directory must + not already exist. - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. + 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 @@ -809,7 +837,7 @@ def move(src, dst, copy_function=copy2): sys.audit("shutil.move", src, dst) real_dst = dst if os.path.isdir(dst): - if _samefile(src, dst): + if _samefile(src, dst) and not os.path.islink(src): # We might be on a case insensitive filesystem, # perform the rename anyway. os.rename(src, dst) |