diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst index f0a81a093b435b..f2d2f2498f9c3f 100644 --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -142,6 +142,9 @@ The module defines the following user-callable items: .. versionchanged:: 3.12 Added *delete_on_close* parameter. + .. versionchanged:: next + Added support for the :term:`path-like object` protocol. + .. class:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None) @@ -217,6 +220,9 @@ The module defines the following user-callable items: .. versionchanged:: 3.12 Added the *delete* parameter. + .. versionchanged:: next + Added support for the :term:`path-like object` protocol. + .. function:: mkstemp(suffix=None, prefix=None, dir=None, text=False) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 5b03bd9e5a8caf..22b5010e99e061 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1218,6 +1218,14 @@ sysconfig (Contributed by Xuehai Pan in :gh:`131799`.) +tempfile +-------- + +* :func:`tempfile.NamedTemporaryFile` and :func:`~tempfile.TemporaryDirectory` + now return a :term:`path-like object`. + (Contributed by Barney Gale in :gh:`87646`.) + + threading --------- diff --git a/Lib/tempfile.py b/Lib/tempfile.py index cadb0bed3cce3b..b1e6dfe786025b 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -525,6 +525,10 @@ def func_wrapper(*args, **kwargs): setattr(self, name, a) return a + def __fspath__(self): + """Return the filesystem path of the temporary file.""" + return self.name + # The underlying __enter__ method returns the wrong object # (self.file) so override it to return the wrapper def __enter__(self): @@ -962,6 +966,10 @@ def _cleanup(cls, name, warn_message, ignore_errors=False, delete=True): def __repr__(self): return "<{} {!r}>".format(self.__class__.__name__, self.name) + def __fspath__(self): + """Return the filesystem path of the temporary directory.""" + return self.name + def __enter__(self): return self.name diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index d46d3c0f040601..229d17fe6fb160 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -950,8 +950,12 @@ def do_create(self, dir=None, pre="", suf="", delete=True): delete=delete) self.nameCheck(file.name, dir, pre, suf) + self.nameCheck(os.fspath(file), dir, pre, suf) return file + def test_pathlike(self): + tmp = self.do_create() + self.assertIsInstance(tmp, os.PathLike) def test_basic(self): # NamedTemporaryFile can create files @@ -1623,9 +1627,14 @@ def do_create(self, dir=None, pre="", suf="", recurse=1, dirs=1, files=1, dir=dir, prefix=pre, suffix=suf, ignore_cleanup_errors=ignore_cleanup_errors) self.nameCheck(tmp.name, dir, pre, suf) + self.nameCheck(os.fspath(tmp), dir, pre, suf) self.do_create2(tmp.name, recurse, dirs, files) return tmp + def test_pathlike(self): + tmp = self.do_create() + self.assertIsInstance(tmp, os.PathLike) + def do_create2(self, path, recurse=1, dirs=1, files=1): # Create subdirectories and some files if recurse: diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index b7840d0f945a66..8a6d162de817fe 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -1377,12 +1377,17 @@ def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True, "metadata_encoding is only supported for reading files") # Check if we were passed a file-like object - if isinstance(file, os.PathLike): - file = os.fspath(file) - if isinstance(file, str): + if hasattr(file, 'read') or hasattr(file, 'write'): + self._filePassed = 1 + self.fp = file + if isinstance(file, os.PathLike): + self.filename = os.fspath(file) + else: + self.filename = getattr(file, 'name', None) + else: # No, it's a filename self._filePassed = 0 - self.filename = file + self.filename = os.fspath(file) modeDict = {'r' : 'rb', 'w': 'w+b', 'x': 'x+b', 'a' : 'r+b', 'r+b': 'w+b', 'w+b': 'wb', 'x+b': 'xb'} filemode = modeDict[mode] @@ -1395,10 +1400,6 @@ def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True, continue raise break - else: - self._filePassed = 1 - self.fp = file - self.filename = getattr(file, 'name', None) self._fileRefCnt = 1 self._lock = threading.RLock() self._seekable = True diff --git a/Misc/NEWS.d/next/Library/2024-01-30-21-07-20.gh-issue-87646.TQUZMn.rst b/Misc/NEWS.d/next/Library/2024-01-30-21-07-20.gh-issue-87646.TQUZMn.rst new file mode 100644 index 00000000000000..18272be258e022 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-30-21-07-20.gh-issue-87646.TQUZMn.rst @@ -0,0 +1,3 @@ +Return a :term:`path-like object` from :func:`tempfile.NamedTemporaryFile` +and :func:`~tempfile.TemporaryDirectory`. (Contributed by Barney Gale in +:gh:`87646`.) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy