Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions Doc/library/tempfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ is recommended to use keyword arguments for clarity.

The module defines the following user-callable items:

.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None)
.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)

Return a :term:`file-like object` that can be used as a temporary storage area.
The file is created securely, using the same rules as :func:`mkstemp`. It will be destroyed as soon
Expand All @@ -49,7 +49,7 @@ The module defines the following user-callable items:
The *mode* parameter defaults to ``'w+b'`` so that the file created can
be read and written without being closed. Binary mode is used so that it
behaves consistently on all platforms without regard for the data that is
stored. *buffering*, *encoding* and *newline* are interpreted as for
stored. *buffering*, *encoding*, *errors* and *newline* are interpreted as for
:func:`open`.

The *dir*, *prefix* and *suffix* parameters have the same meaning and
Expand All @@ -66,8 +66,11 @@ The module defines the following user-callable items:

The :py:data:`os.O_TMPFILE` flag is now used if available.

.. versionchanged:: 3.8
Added *errors* parameter.

.. function:: NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True)

.. function:: NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True, *, errors=None)

This function operates exactly as :func:`TemporaryFile` does, except that
the file is guaranteed to have a visible name in the file system (on
Expand All @@ -82,8 +85,11 @@ The module defines the following user-callable items:
attribute is the underlying true file object. This file-like object can
be used in a :keyword:`with` statement, just like a normal file.

.. versionchanged:: 3.8
Added *errors* parameter.


.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None)
.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)

This function operates exactly as :func:`TemporaryFile` does, except that
data is spooled in memory until the file size exceeds *max_size*, or
Expand All @@ -104,6 +110,9 @@ The module defines the following user-callable items:
.. versionchanged:: 3.3
the truncate method now accepts a ``size`` argument.

.. versionchanged:: 3.8
Added *errors* parameter.


.. function:: TemporaryDirectory(suffix=None, prefix=None, dir=None)

Expand Down
35 changes: 16 additions & 19 deletions Lib/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ def __iter__(self):

def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
newline=None, suffix=None, prefix=None,
dir=None, delete=True):
dir=None, delete=True, *, errors=None):
"""Create and return a temporary file.
Arguments:
'prefix', 'suffix', 'dir' -- as for mkstemp.
Expand All @@ -526,6 +526,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
'encoding' -- the encoding argument to io.open (default None)
'newline' -- the newline argument to io.open (default None)
'delete' -- whether the file is deleted on close (default True).
'errors' -- the errors argument to io.open (default None)
The file is created as mkstemp() would do it.

Returns an object with a file-like interface; the name of the file
Expand All @@ -545,7 +546,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
(fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
try:
file = _io.open(fd, mode, buffering=buffering,
newline=newline, encoding=encoding)
newline=newline, encoding=encoding, errors=errors)

return _TemporaryFileWrapper(file, name, delete)
except BaseException:
Expand All @@ -566,14 +567,15 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,

def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
newline=None, suffix=None, prefix=None,
dir=None):
dir=None, *, errors=None):
"""Create and return a temporary file.
Arguments:
'prefix', 'suffix', 'dir' -- as for mkstemp.
'mode' -- the mode argument to io.open (default "w+b").
'buffering' -- the buffer size argument to io.open (default -1).
'encoding' -- the encoding argument to io.open (default None)
'newline' -- the newline argument to io.open (default None)
'errors' -- the errors argument to io.open (default None)
The file is created as mkstemp() would do it.

Returns an object with a file-like interface. The file has no
Expand Down Expand Up @@ -607,7 +609,8 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
else:
try:
return _io.open(fd, mode, buffering=buffering,
newline=newline, encoding=encoding)
newline=newline, encoding=encoding,
errors=errors)
except:
_os.close(fd)
raise
Expand All @@ -617,7 +620,7 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
try:
_os.unlink(name)
return _io.open(fd, mode, buffering=buffering,
newline=newline, encoding=encoding)
newline=newline, encoding=encoding, errors=errors)
except:
_os.close(fd)
raise
Expand All @@ -631,7 +634,7 @@ class SpooledTemporaryFile:

def __init__(self, max_size=0, mode='w+b', buffering=-1,
encoding=None, newline=None,
suffix=None, prefix=None, dir=None):
suffix=None, prefix=None, dir=None, *, errors=None):
if 'b' in mode:
self._file = _io.BytesIO()
else:
Expand All @@ -644,7 +647,7 @@ def __init__(self, max_size=0, mode='w+b', buffering=-1,
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
'suffix': suffix, 'prefix': prefix,
'encoding': encoding, 'newline': newline,
'dir': dir}
'dir': dir, 'errors': errors}

def _check(self, file):
if self._rolled: return
Expand Down Expand Up @@ -690,12 +693,11 @@ def closed(self):

@property
def encoding(self):
try:
return self._file.encoding
except AttributeError:
if 'b' in self._TemporaryFileArgs['mode']:
raise
return self._TemporaryFileArgs['encoding']
return self._file.encoding

@property
def errors(self):
return self._file.errors

def fileno(self):
self.rollover()
Expand Down Expand Up @@ -723,12 +725,7 @@ def name(self):

@property
def newlines(self):
try:
return self._file.newlines
except AttributeError:
if 'b' in self._TemporaryFileArgs['mode']:
raise
return self._TemporaryFileArgs['newline']
return self._file.newlines

def read(self, *args):
return self._file.read(*args)
Expand Down
11 changes: 10 additions & 1 deletion Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,8 @@ def test_properties(self):
f.newlines
with self.assertRaises(AttributeError):
f.encoding
with self.assertRaises(AttributeError):
f.errors

f.write(b'x')
self.assertTrue(f._rolled)
Expand All @@ -1103,6 +1105,8 @@ def test_properties(self):
f.newlines
with self.assertRaises(AttributeError):
f.encoding
with self.assertRaises(AttributeError):
f.errors

def test_text_mode(self):
# Creating a SpooledTemporaryFile with a text mode should produce
Expand All @@ -1119,6 +1123,7 @@ def test_text_mode(self):
self.assertIsNone(f.name)
self.assertIsNone(f.newlines)
self.assertIsNone(f.encoding)
self.assertIsNone(f.errors)

f.write("xyzzy\n")
f.seek(0)
Expand All @@ -1132,10 +1137,12 @@ def test_text_mode(self):
self.assertIsNotNone(f.name)
self.assertEqual(f.newlines, os.linesep)
self.assertIsNotNone(f.encoding)
self.assertIsNotNone(f.errors)

def test_text_newline_and_encoding(self):
f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10,
newline='', encoding='utf-8')
newline='', encoding='utf-8',
errors='ignore')
f.write("\u039B\r\n")
f.seek(0)
self.assertEqual(f.read(), "\u039B\r\n")
Expand All @@ -1144,6 +1151,7 @@ def test_text_newline_and_encoding(self):
self.assertIsNone(f.name)
self.assertIsNone(f.newlines)
self.assertIsNone(f.encoding)
self.assertIsNone(f.errors)

f.write("\u039B" * 20 + "\r\n")
f.seek(0)
Expand All @@ -1153,6 +1161,7 @@ def test_text_newline_and_encoding(self):
self.assertIsNotNone(f.name)
self.assertIsNotNone(f.newlines)
self.assertEqual(f.encoding, 'utf-8')
self.assertEqual(f.errors, 'ignore')

def test_context_manager_before_rollover(self):
# A SpooledTemporaryFile can be used as a context manager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The file classes in *tempfile* now accept an *errors* parameter that
complements the already existing *encoding*. Patch by Stephan Hohe.