summaryrefslogtreecommitdiffstats
path: root/Lib/tempfile.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-12-05 13:58:36 (GMT)
committerGitHub <noreply@github.com>2023-12-05 13:58:36 (GMT)
commit5acfb8258afa1ecb445f699585ffbaf7529a640d (patch)
tree12c99dc748510b9e6f8e6226505addfc99c2af6d /Lib/tempfile.py
parent68f05dd82976e0af4e3af0f65fe226d138ff55f7 (diff)
downloadcpython-5acfb8258afa1ecb445f699585ffbaf7529a640d.zip
cpython-5acfb8258afa1ecb445f699585ffbaf7529a640d.tar.gz
cpython-5acfb8258afa1ecb445f699585ffbaf7529a640d.tar.bz2
[3.12] bpo-43153: Don't mask `PermissionError` with `NotADirectoryError` during tempdirectory cleanup (GH-29940) (GH-112753)
(cherry picked from commit 8cdfee1bb902fd1e38d79170b751ef13a0907262) Co-authored-by: Ken Jin <kenjin@python.org> Co-authored-by: andrei kulakov <andrei.avk@gmail.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Lib/tempfile.py')
-rw-r--r--Lib/tempfile.py28
1 files changed, 26 insertions, 2 deletions
diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index 2b4f431..55403ad 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -41,6 +41,7 @@ import warnings as _warnings
import io as _io
import os as _os
import shutil as _shutil
+import stat as _stat
import errno as _errno
from random import Random as _Random
import sys as _sys
@@ -889,8 +890,31 @@ class TemporaryDirectory:
try:
_os.unlink(path)
- # PermissionError is raised on FreeBSD for directories
- except (IsADirectoryError, PermissionError):
+ except IsADirectoryError:
+ cls._rmtree(path, ignore_errors=ignore_errors)
+ except PermissionError:
+ # The PermissionError handler was originally added for
+ # FreeBSD in directories, but it seems that it is raised
+ # on Windows too.
+ # bpo-43153: Calling _rmtree again may
+ # raise NotADirectoryError and mask the PermissionError.
+ # So we must re-raise the current PermissionError if
+ # path is not a directory.
+ try:
+ st = _os.lstat(path)
+ except OSError:
+ if ignore_errors:
+ return
+ raise
+ if (_stat.S_ISLNK(st.st_mode) or
+ not _stat.S_ISDIR(st.st_mode) or
+ (hasattr(st, 'st_file_attributes') and
+ st.st_file_attributes & _stat.FILE_ATTRIBUTE_REPARSE_POINT and
+ st.st_reparse_tag == _stat.IO_REPARSE_TAG_MOUNT_POINT)
+ ):
+ if ignore_errors:
+ return
+ raise
cls._rmtree(path, ignore_errors=ignore_errors)
except FileNotFoundError:
pass