Skip to content
6 changes: 6 additions & 0 deletions Doc/library/tempfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
8 changes: 8 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------

Expand Down
8 changes: 8 additions & 0 deletions Lib/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 9 additions & 8 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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`.)
Loading