summaryrefslogtreecommitdiffstats
path: root/Lib/tempfile.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-05-31 08:30:37 (GMT)
committerGitHub <noreply@github.com>2019-05-31 08:30:37 (GMT)
commite9b51c0ad81da1da11ae65840ac8b50a8521373c (patch)
tree612f275e9aa504fdf3e5e18d736f19bf56fdb06f /Lib/tempfile.py
parent38ab7d4721b422547f7b46b9d68968863fa70573 (diff)
downloadcpython-e9b51c0ad81da1da11ae65840ac8b50a8521373c.zip
cpython-e9b51c0ad81da1da11ae65840ac8b50a8521373c.tar.gz
cpython-e9b51c0ad81da1da11ae65840ac8b50a8521373c.tar.bz2
bpo-26660, bpo-35144: Fix permission errors in TemporaryDirectory cleanup. (GH-10320)
TemporaryDirectory.cleanup() failed when non-writeable or non-searchable files or directories were created inside a temporary directory.
Diffstat (limited to 'Lib/tempfile.py')
-rw-r--r--Lib/tempfile.py34
1 files changed, 32 insertions, 2 deletions
diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index a66d6f3..e8b111e 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -778,8 +778,38 @@ class TemporaryDirectory(object):
warn_message="Implicitly cleaning up {!r}".format(self))
@classmethod
+ def _rmtree(cls, name):
+ def onerror(func, path, exc_info):
+ if issubclass(exc_info[0], PermissionError):
+ def resetperms(path):
+ try:
+ _os.chflags(path, 0)
+ except AttributeError:
+ pass
+ _os.chmod(path, 0o700)
+
+ try:
+ if path != name:
+ resetperms(_os.path.dirname(path))
+ resetperms(path)
+
+ try:
+ _os.unlink(path)
+ # PermissionError is raised on FreeBSD for directories
+ except (IsADirectoryError, PermissionError):
+ cls._rmtree(path)
+ except FileNotFoundError:
+ pass
+ elif issubclass(exc_info[0], FileNotFoundError):
+ pass
+ else:
+ raise
+
+ _shutil.rmtree(name, onerror=onerror)
+
+ @classmethod
def _cleanup(cls, name, warn_message):
- _shutil.rmtree(name)
+ cls._rmtree(name)
_warnings.warn(warn_message, ResourceWarning)
def __repr__(self):
@@ -793,4 +823,4 @@ class TemporaryDirectory(object):
def cleanup(self):
if self._finalizer.detach():
- _shutil.rmtree(self.name)
+ self._rmtree(self.name)