Deprecate old compatibility `tempfile._TemporaryFileWrapper` name, schedule it to be removed in Python 3.21
Co-authored-by: sobolevn <mail@sobolevn.me>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
* Soft-deprecated since Python 3.15, using ``'F'`` and ``'D'`` type codes are now
deprecated. These codes will be removed in Python 3.21. Use instead
two-letter forms ``'Zf'`` and ``'Zd'``.
+
+* :mod:`tempfile`:
+
+ * ``tempfile._TemporaryFileWrapper`` will be removed in Python 3.21. Use the
+ public :class:`tempfile.TemporaryFileWrapper` instead.
This module creates temporary files and directories. It works on all
supported platforms. :class:`TemporaryFile`, :class:`NamedTemporaryFile`,
-:class:`TemporaryDirectory`, and :class:`SpooledTemporaryFile` are high-level
-interfaces which provide automatic cleanup and can be used as
-:term:`context managers <context manager>`. :func:`mkstemp` and
-:func:`mkdtemp` are lower-level functions which require manual cleanup.
+:class:`TemporaryFileWrapper`, :class:`TemporaryDirectory`, and
+:class:`SpooledTemporaryFile` are high-level interfaces which provide
+automatic cleanup and can be used as :term:`context managers
+<context manager>`. :func:`mkstemp` and :func:`mkdtemp` are lower-level
+functions which require manual cleanup.
All the user-callable functions and constructors take additional arguments which
allow direct control over the location and name of temporary files and
:func:`TemporaryFile` with *delete* and *delete_on_close* parameters that
determine whether and how the named file should be automatically deleted.
- The returned object is always a :term:`file-like object` whose :attr:`!file`
- attribute is the underlying true file object. This file-like object
- can be used in a :keyword:`with` statement, just like a normal file. The
- name of the temporary file can be retrieved from the :attr:`!name` attribute
- of the returned file-like object. On Unix, unlike with the
- :func:`TemporaryFile`, the directory entry does not get unlinked immediately
- after the file creation.
+ The returned object is always a :class:`TemporaryFileWrapper` instance
+ (a :term:`file-like object`) whose :attr:`~TemporaryFileWrapper.file` attribute is the underlying
+ true file object. This file-like object can be used in a :keyword:`with`
+ statement, just like a normal file. The name of the temporary file can be
+ retrieved from the :attr:`!name` attribute of the returned file-like object.
+ On Unix, unlike with the :func:`TemporaryFile`, the directory entry does not
+ get unlinked immediately after the file creation.
If *delete* is true (the default) and *delete_on_close* is true (the
default), the file is deleted as soon as it is closed. If *delete* is true
.. versionchanged:: 3.12
Added *delete_on_close* parameter.
+.. class:: TemporaryFileWrapper(file, name, delete=True, delete_on_close=True)
+
+ A mutable wrapper returned by :func:`NamedTemporaryFile`. It wraps the
+ underlying file object, delegating attribute access to it, and ensures
+ the temporary file is deleted when appropriate.
+
+ .. attribute:: file
+
+ The underlying :term:`file-like object`.
+
+ .. attribute:: name
+
+ The file name of the temporary file.
+
+ .. method:: close()
+
+ Close the temporary file, possibly deleting it depending on the
+ *delete* and *delete_on_close* arguments passed to
+ :func:`NamedTemporaryFile`.
+
+ .. note::
+
+ ``tempfile._TemporaryFileWrapper`` is kept as a backwards compatible
+ deprecated alias for this class.
+ It will be removed in Python 3.21
+
+ .. versionadded:: next
+
.. class:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)
two-letter forms ``'Zf'`` and ``'Zd'``.
(Contributed by Sergey B Kirpichev in :gh:`121249`.)
+* :mod:`tempfile`
+
+ * The private ``tempfile._TemporaryFileWrapper`` name is deprecated
+ and is slated for removal in Python 3.21.
+ Use the new public :class:`tempfile.TemporaryFileWrapper` instead,
+ which is the return type of :func:`tempfile.NamedTemporaryFile`.
+
.. Add deprecations above alphabetically, not here at the end.
.. include:: ../deprecations/pending-removal-in-3.17.rst
"TMP_MAX", "gettempprefix", # constants
"tempdir", "gettempdir",
"gettempprefixb", "gettempdirb",
+ "TemporaryFileWrapper",
]
_warnings.warn(self.warn_message, ResourceWarning)
-class _TemporaryFileWrapper:
+class TemporaryFileWrapper:
"""Temporary file wrapper
This class provides a wrapper around files opened for
for line in self.file:
yield line
+def __getattr__(name):
+ if name == "_TemporaryFileWrapper":
+ _warnings._deprecated(
+ "tempfile._TemporaryFileWrapper",
+ message=(
+ "{name!r} is deprecated and slated for removal in Python {remove}. "
+ "Use tempfile.TemporaryFileWrapper instead."
+ ),
+ remove=(3, 21),
+ )
+ return TemporaryFileWrapper
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
+
def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
newline=None, suffix=None, prefix=None,
dir=None, delete=True, *, errors=None,
raw = getattr(file, 'buffer', file)
raw = getattr(raw, 'raw', raw)
raw.name = name
- return _TemporaryFileWrapper(file, name, delete, delete_on_close)
+ return TemporaryFileWrapper(file, name, delete, delete_on_close)
except:
file.close()
raise
"template" : 1,
"SpooledTemporaryFile" : 1,
"TemporaryDirectory" : 1,
+ "TemporaryFileWrapper" : 1,
}
unexp = []
def test_basic(self):
# NamedTemporaryFile can create files
- self.do_create()
+ f = self.do_create()
+ self.assertIsInstance(f, tempfile.TemporaryFileWrapper)
self.do_create(pre="a")
self.do_create(suf="b")
self.do_create(pre="a", suf="b")
self.do_create(pre="aa", suf=".txt")
+ def test_in_all(self):
+ self.assertIn("TemporaryFileWrapper", tempfile.__all__)
+
+ def test_deprecated_TemporaryFileWrapper_alias(self):
+ # gh-152586: _TemporaryFileWrapper is a deprecated alias
+ # for the public TemporaryFileWrapper class.
+ with self.assertWarns(DeprecationWarning):
+ obj = tempfile._TemporaryFileWrapper
+ self.assertIs(obj, tempfile.TemporaryFileWrapper)
+
def test_method_lookup(self):
# Issue #18879: Looking up a temporary file method should keep it
# alive long enough.
try:
with self.assertWarnsRegex(
expected_warning=ResourceWarning,
- expected_regex=r"Implicitly cleaning up <_TemporaryFileWrapper file=.*>",
+ expected_regex=r"Implicitly cleaning up <TemporaryFileWrapper file=.*>",
):
tmp_name = my_func(dir)
support.gc_collect()
def test_unexpected_error(self):
dir = tempfile.mkdtemp()
self.addCleanup(os_helper.rmtree, dir)
- with mock.patch('tempfile._TemporaryFileWrapper') as mock_ntf, \
+ with mock.patch('tempfile.TemporaryFileWrapper') as mock_ntf, \
mock.patch('io.open', mock.mock_open()) as mock_open:
mock_ntf.side_effect = KeyboardInterrupt()
with self.assertRaises(KeyboardInterrupt):
def test_with(self):
addbase = urllib.response.addbase(self.fp)
- self.assertIsInstance(addbase, tempfile._TemporaryFileWrapper)
+ self.assertIsInstance(addbase, tempfile.TemporaryFileWrapper)
def f():
with addbase as spam:
__all__ = ['addbase', 'addclosehook', 'addinfo', 'addinfourl']
-class addbase(tempfile._TemporaryFileWrapper):
+class addbase(tempfile.TemporaryFileWrapper):
"""Base class for addinfo and addclosehook. Is a good idea for garbage collection."""
# XXX Add a method to expose the timeout on the underlying socket?
--- /dev/null
+:class:`!tempfile._TemporaryFileWrapper` has been renamed to the public :class:`tempfile.TemporaryFileWrapper`. The old private name is kept as a deprecated alias and will be removed in Python 3.21.