[Python-checkins] gh-100131: Add optional delete parameter to tempfile.TemporaryDirectory() (#100132)
gpshead
webhook-mailer at python.org
Fri Mar 24 17:52:14 EDT 2023
https://github.com/python/cpython/commit/64cb1a4f0f0bc733a33ad7a6520e749ca1cdd43f
commit: 64cb1a4f0f0bc733a33ad7a6520e749ca1cdd43f
branch: main
author: JakobDev <jakobdev at gmx.de>
committer: gpshead <greg at krypto.org>
date: 2023-03-24T14:52:06-07:00
summary:
gh-100131: Add optional delete parameter to tempfile.TemporaryDirectory() (#100132)
Add optional delete parameter to tempfile.TemporaryDirectory().
Co-authored-by: Gregory P. Smith <greg at krypto.org>
files:
A Misc/NEWS.d/next/Library/2022-12-09-11-21-38.gh-issue-100131.v863yR.rst
M Doc/library/tempfile.rst
M Lib/tempfile.py
M Lib/test/test_tempfile.py
diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst
index b6d4f5dd05bb..61358eb76925 100644
--- a/Doc/library/tempfile.rst
+++ b/Doc/library/tempfile.rst
@@ -173,7 +173,7 @@ The module defines the following user-callable items:
or text *mode* was specified).
-.. class:: TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False)
+.. class:: TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False, *, delete=True)
This class securely creates a temporary directory using the same rules as :func:`mkdtemp`.
The resulting object can be used as a context manager (see
@@ -195,6 +195,12 @@ The module defines the following user-callable items:
(the :func:`cleanup` call, exiting the context manager, when the object
is garbage-collected or during interpreter shutdown).
+ The *delete* parameter can be used to disable cleanup of the directory tree
+ upon exiting the context. While it may seem unusual for a context manager
+ to disable the action taken when exiting the context, it can be useful during
+ debugging or when you need your cleanup behavior to be conditional based on
+ other logic.
+
.. audit-event:: tempfile.mkdtemp fullpath tempfile.TemporaryDirectory
.. versionadded:: 3.2
@@ -202,6 +208,9 @@ The module defines the following user-callable items:
.. versionchanged:: 3.10
Added *ignore_cleanup_errors* parameter.
+ .. versionchanged:: 3.12
+ Added the *delete* parameter.
+
.. function:: mkstemp(suffix=None, prefix=None, dir=None, text=False)
diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index cf06092f826b..4732eb0efe1f 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -850,17 +850,26 @@ class TemporaryDirectory:
...
Upon exiting the context, the directory and everything contained
- in it are removed.
+ in it are removed (unless delete=False is passed or an exception
+ is raised during cleanup and ignore_cleanup_errors is not True).
+
+ Optional Arguments:
+ suffix - A str suffix for the directory name. (see mkdtemp)
+ prefix - A str prefix for the directory name. (see mkdtemp)
+ dir - A directory to create this temp dir in. (see mkdtemp)
+ ignore_cleanup_errors - False; ignore exceptions during cleanup?
+ delete - True; whether the directory is automatically deleted.
"""
def __init__(self, suffix=None, prefix=None, dir=None,
- ignore_cleanup_errors=False):
+ ignore_cleanup_errors=False, *, delete=True):
self.name = mkdtemp(suffix, prefix, dir)
self._ignore_cleanup_errors = ignore_cleanup_errors
+ self._delete = delete
self._finalizer = _weakref.finalize(
self, self._cleanup, self.name,
warn_message="Implicitly cleaning up {!r}".format(self),
- ignore_errors=self._ignore_cleanup_errors)
+ ignore_errors=self._ignore_cleanup_errors, delete=self._delete)
@classmethod
def _rmtree(cls, name, ignore_errors=False):
@@ -894,9 +903,10 @@ def resetperms(path):
_shutil.rmtree(name, onexc=onexc)
@classmethod
- def _cleanup(cls, name, warn_message, ignore_errors=False):
- cls._rmtree(name, ignore_errors=ignore_errors)
- _warnings.warn(warn_message, ResourceWarning)
+ def _cleanup(cls, name, warn_message, ignore_errors=False, delete=True):
+ if delete:
+ cls._rmtree(name, ignore_errors=ignore_errors)
+ _warnings.warn(warn_message, ResourceWarning)
def __repr__(self):
return "<{} {!r}>".format(self.__class__.__name__, self.name)
@@ -905,7 +915,8 @@ def __enter__(self):
return self.name
def __exit__(self, exc, value, tb):
- self.cleanup()
+ if self._delete:
+ self.cleanup()
def cleanup(self):
if self._finalizer.detach() or _os.path.exists(self.name):
diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py
index 7c2c8de7a2e6..90155487cff5 100644
--- a/Lib/test/test_tempfile.py
+++ b/Lib/test/test_tempfile.py
@@ -12,6 +12,7 @@
import types
import weakref
import gc
+import shutil
from unittest import mock
import unittest
@@ -1837,6 +1838,11 @@ def test_flags(self):
d.cleanup()
self.assertFalse(os.path.exists(d.name))
+ def test_delete_false(self):
+ with tempfile.TemporaryDirectory(delete=False) as working_dir:
+ pass
+ self.assertTrue(os.path.exists(working_dir))
+ shutil.rmtree(working_dir)
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2022-12-09-11-21-38.gh-issue-100131.v863yR.rst b/Misc/NEWS.d/next/Library/2022-12-09-11-21-38.gh-issue-100131.v863yR.rst
new file mode 100644
index 000000000000..07891f2c1e9e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-12-09-11-21-38.gh-issue-100131.v863yR.rst
@@ -0,0 +1 @@
+Added an optional ``delete`` keyword argument to :class:`tempfile.TemporaryDirectory`.
More information about the Python-checkins
mailing list