diff options
| author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-12-05 13:58:36 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-05 13:58:36 (GMT) |
| commit | 5acfb8258afa1ecb445f699585ffbaf7529a640d (patch) | |
| tree | 12c99dc748510b9e6f8e6226505addfc99c2af6d /Lib/tempfile.py | |
| parent | 68f05dd82976e0af4e3af0f65fe226d138ff55f7 (diff) | |
| download | cpython-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.py | 28 |
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 |
