summaryrefslogtreecommitdiffstats
path: root/Lib/shutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/shutil.py')
-rw-r--r--Lib/shutil.py45
1 files changed, 34 insertions, 11 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py
index dd93872..93b00d7 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -590,23 +590,21 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
dirs_exist_ok=dirs_exist_ok)
if hasattr(os.stat_result, 'st_file_attributes'):
- def _rmtree_islink(path):
- try:
- st = os.lstat(path)
- return (stat.S_ISLNK(st.st_mode) or
- (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
- and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
- except OSError:
- return False
+ def _rmtree_islink(st):
+ return (stat.S_ISLNK(st.st_mode) or
+ (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
+ and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
else:
- def _rmtree_islink(path):
- return os.path.islink(path)
+ def _rmtree_islink(st):
+ return stat.S_ISLNK(st.st_mode)
# version vulnerable to race conditions
def _rmtree_unsafe(path, onexc):
try:
with os.scandir(path) as scandir_it:
entries = list(scandir_it)
+ except FileNotFoundError:
+ return
except OSError as err:
onexc(os.scandir, path, err)
entries = []
@@ -614,6 +612,8 @@ def _rmtree_unsafe(path, onexc):
fullname = entry.path
try:
is_dir = entry.is_dir(follow_symlinks=False)
+ except FileNotFoundError:
+ continue
except OSError:
is_dir = False
@@ -624,6 +624,8 @@ def _rmtree_unsafe(path, onexc):
# a directory with a symlink after the call to
# os.scandir or entry.is_dir above.
raise OSError("Cannot call rmtree on a symbolic link")
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.path.islink, fullname, err)
continue
@@ -631,10 +633,14 @@ def _rmtree_unsafe(path, onexc):
else:
try:
os.unlink(fullname)
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.unlink, fullname, err)
try:
os.rmdir(path)
+ except FileNotFoundError:
+ pass
except OSError as err:
onexc(os.rmdir, path, err)
@@ -643,6 +649,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
try:
with os.scandir(topfd) as scandir_it:
entries = list(scandir_it)
+ except FileNotFoundError:
+ return
except OSError as err:
err.filename = path
onexc(os.scandir, path, err)
@@ -651,6 +659,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
fullname = os.path.join(path, entry.name)
try:
is_dir = entry.is_dir(follow_symlinks=False)
+ except FileNotFoundError:
+ continue
except OSError:
is_dir = False
else:
@@ -658,6 +668,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
try:
orig_st = entry.stat(follow_symlinks=False)
is_dir = stat.S_ISDIR(orig_st.st_mode)
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.lstat, fullname, err)
continue
@@ -665,6 +677,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
try:
dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
dirfd_closed = False
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.open, fullname, err)
else:
@@ -675,6 +689,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
os.close(dirfd)
dirfd_closed = True
os.rmdir(entry.name, dir_fd=topfd)
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.rmdir, fullname, err)
else:
@@ -692,6 +708,8 @@ def _rmtree_safe_fd(topfd, path, onexc):
else:
try:
os.unlink(entry.name, dir_fd=topfd)
+ except FileNotFoundError:
+ continue
except OSError as err:
onexc(os.unlink, fullname, err)
@@ -781,7 +799,12 @@ def rmtree(path, ignore_errors=False, onerror=None, *, onexc=None, dir_fd=None):
if dir_fd is not None:
raise NotImplementedError("dir_fd unavailable on this platform")
try:
- if _rmtree_islink(path):
+ st = os.lstat(path)
+ except OSError as err:
+ onexc(os.lstat, path, err)
+ return
+ try:
+ if _rmtree_islink(st):
# symlinks to directories are forbidden, see bug #1669
raise OSError("Cannot call rmtree on a symbolic link")
except OSError as err: