bpo-27300: Add the errors parameter to tempfile classes. (GH-6696)
This commit is contained in:
parent
0e61dffdba
commit
825aab95fd
|
@ -31,7 +31,7 @@ is recommended to use keyword arguments for clarity.
|
||||||
|
|
||||||
The module defines the following user-callable items:
|
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.
|
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
|
The file is created securely, using the same rules as :func:`mkstemp`. It will be destroyed as soon
|
||||||
|
@ -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
|
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
|
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
|
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`.
|
:func:`open`.
|
||||||
|
|
||||||
The *dir*, *prefix* and *suffix* parameters have the same meaning and
|
The *dir*, *prefix* and *suffix* parameters have the same meaning and
|
||||||
|
@ -66,8 +66,11 @@ The module defines the following user-callable items:
|
||||||
|
|
||||||
The :py:data:`os.O_TMPFILE` flag is now used if available.
|
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
|
This function operates exactly as :func:`TemporaryFile` does, except that
|
||||||
the file is guaranteed to have a visible name in the file system (on
|
the file is guaranteed to have a visible name in the file system (on
|
||||||
|
@ -82,8 +85,11 @@ The module defines the following user-callable items:
|
||||||
attribute is the underlying true file object. This file-like object can
|
attribute is the underlying true file object. This file-like object can
|
||||||
be used in a :keyword:`with` statement, just like a normal file.
|
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
|
This function operates exactly as :func:`TemporaryFile` does, except that
|
||||||
data is spooled in memory until the file size exceeds *max_size*, or
|
data is spooled in memory until the file size exceeds *max_size*, or
|
||||||
|
@ -104,6 +110,9 @@ The module defines the following user-callable items:
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
the truncate method now accepts a ``size`` argument.
|
the truncate method now accepts a ``size`` argument.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8
|
||||||
|
Added *errors* parameter.
|
||||||
|
|
||||||
|
|
||||||
.. function:: TemporaryDirectory(suffix=None, prefix=None, dir=None)
|
.. function:: TemporaryDirectory(suffix=None, prefix=None, dir=None)
|
||||||
|
|
||||||
|
|
|
@ -519,7 +519,7 @@ class _TemporaryFileWrapper:
|
||||||
|
|
||||||
def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
||||||
newline=None, suffix=None, prefix=None,
|
newline=None, suffix=None, prefix=None,
|
||||||
dir=None, delete=True):
|
dir=None, delete=True, *, errors=None):
|
||||||
"""Create and return a temporary file.
|
"""Create and return a temporary file.
|
||||||
Arguments:
|
Arguments:
|
||||||
'prefix', 'suffix', 'dir' -- as for mkstemp.
|
'prefix', 'suffix', 'dir' -- as for mkstemp.
|
||||||
|
@ -528,6 +528,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
||||||
'encoding' -- the encoding argument to io.open (default None)
|
'encoding' -- the encoding argument to io.open (default None)
|
||||||
'newline' -- the newline 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).
|
'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.
|
The file is created as mkstemp() would do it.
|
||||||
|
|
||||||
Returns an object with a file-like interface; the name of the file
|
Returns an object with a file-like interface; the name of the file
|
||||||
|
@ -547,7 +548,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
||||||
(fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
|
(fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
|
||||||
try:
|
try:
|
||||||
file = _io.open(fd, mode, buffering=buffering,
|
file = _io.open(fd, mode, buffering=buffering,
|
||||||
newline=newline, encoding=encoding)
|
newline=newline, encoding=encoding, errors=errors)
|
||||||
|
|
||||||
return _TemporaryFileWrapper(file, name, delete)
|
return _TemporaryFileWrapper(file, name, delete)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
|
@ -568,7 +569,7 @@ else:
|
||||||
|
|
||||||
def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
|
||||||
newline=None, suffix=None, prefix=None,
|
newline=None, suffix=None, prefix=None,
|
||||||
dir=None):
|
dir=None, *, errors=None):
|
||||||
"""Create and return a temporary file.
|
"""Create and return a temporary file.
|
||||||
Arguments:
|
Arguments:
|
||||||
'prefix', 'suffix', 'dir' -- as for mkstemp.
|
'prefix', 'suffix', 'dir' -- as for mkstemp.
|
||||||
|
@ -576,6 +577,7 @@ else:
|
||||||
'buffering' -- the buffer size argument to io.open (default -1).
|
'buffering' -- the buffer size argument to io.open (default -1).
|
||||||
'encoding' -- the encoding argument to io.open (default None)
|
'encoding' -- the encoding argument to io.open (default None)
|
||||||
'newline' -- the newline 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.
|
The file is created as mkstemp() would do it.
|
||||||
|
|
||||||
Returns an object with a file-like interface. The file has no
|
Returns an object with a file-like interface. The file has no
|
||||||
|
@ -609,7 +611,8 @@ else:
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return _io.open(fd, mode, buffering=buffering,
|
return _io.open(fd, mode, buffering=buffering,
|
||||||
newline=newline, encoding=encoding)
|
newline=newline, encoding=encoding,
|
||||||
|
errors=errors)
|
||||||
except:
|
except:
|
||||||
_os.close(fd)
|
_os.close(fd)
|
||||||
raise
|
raise
|
||||||
|
@ -619,7 +622,7 @@ else:
|
||||||
try:
|
try:
|
||||||
_os.unlink(name)
|
_os.unlink(name)
|
||||||
return _io.open(fd, mode, buffering=buffering,
|
return _io.open(fd, mode, buffering=buffering,
|
||||||
newline=newline, encoding=encoding)
|
newline=newline, encoding=encoding, errors=errors)
|
||||||
except:
|
except:
|
||||||
_os.close(fd)
|
_os.close(fd)
|
||||||
raise
|
raise
|
||||||
|
@ -633,7 +636,7 @@ class SpooledTemporaryFile:
|
||||||
|
|
||||||
def __init__(self, max_size=0, mode='w+b', buffering=-1,
|
def __init__(self, max_size=0, mode='w+b', buffering=-1,
|
||||||
encoding=None, newline=None,
|
encoding=None, newline=None,
|
||||||
suffix=None, prefix=None, dir=None):
|
suffix=None, prefix=None, dir=None, *, errors=None):
|
||||||
if 'b' in mode:
|
if 'b' in mode:
|
||||||
self._file = _io.BytesIO()
|
self._file = _io.BytesIO()
|
||||||
else:
|
else:
|
||||||
|
@ -646,7 +649,7 @@ class SpooledTemporaryFile:
|
||||||
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
|
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
|
||||||
'suffix': suffix, 'prefix': prefix,
|
'suffix': suffix, 'prefix': prefix,
|
||||||
'encoding': encoding, 'newline': newline,
|
'encoding': encoding, 'newline': newline,
|
||||||
'dir': dir}
|
'dir': dir, 'errors': errors}
|
||||||
|
|
||||||
def _check(self, file):
|
def _check(self, file):
|
||||||
if self._rolled: return
|
if self._rolled: return
|
||||||
|
@ -692,12 +695,11 @@ class SpooledTemporaryFile:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def encoding(self):
|
def encoding(self):
|
||||||
try:
|
return self._file.encoding
|
||||||
return self._file.encoding
|
|
||||||
except AttributeError:
|
@property
|
||||||
if 'b' in self._TemporaryFileArgs['mode']:
|
def errors(self):
|
||||||
raise
|
return self._file.errors
|
||||||
return self._TemporaryFileArgs['encoding']
|
|
||||||
|
|
||||||
def fileno(self):
|
def fileno(self):
|
||||||
self.rollover()
|
self.rollover()
|
||||||
|
@ -725,12 +727,7 @@ class SpooledTemporaryFile:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def newlines(self):
|
def newlines(self):
|
||||||
try:
|
return self._file.newlines
|
||||||
return self._file.newlines
|
|
||||||
except AttributeError:
|
|
||||||
if 'b' in self._TemporaryFileArgs['mode']:
|
|
||||||
raise
|
|
||||||
return self._TemporaryFileArgs['newline']
|
|
||||||
|
|
||||||
def read(self, *args):
|
def read(self, *args):
|
||||||
return self._file.read(*args)
|
return self._file.read(*args)
|
||||||
|
|
|
@ -1094,6 +1094,8 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
f.newlines
|
f.newlines
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
f.encoding
|
f.encoding
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
f.errors
|
||||||
|
|
||||||
f.write(b'x')
|
f.write(b'x')
|
||||||
self.assertTrue(f._rolled)
|
self.assertTrue(f._rolled)
|
||||||
|
@ -1103,6 +1105,8 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
f.newlines
|
f.newlines
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
f.encoding
|
f.encoding
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
f.errors
|
||||||
|
|
||||||
def test_text_mode(self):
|
def test_text_mode(self):
|
||||||
# Creating a SpooledTemporaryFile with a text mode should produce
|
# Creating a SpooledTemporaryFile with a text mode should produce
|
||||||
|
@ -1119,6 +1123,7 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
self.assertIsNone(f.name)
|
self.assertIsNone(f.name)
|
||||||
self.assertIsNone(f.newlines)
|
self.assertIsNone(f.newlines)
|
||||||
self.assertIsNone(f.encoding)
|
self.assertIsNone(f.encoding)
|
||||||
|
self.assertIsNone(f.errors)
|
||||||
|
|
||||||
f.write("xyzzy\n")
|
f.write("xyzzy\n")
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
@ -1132,10 +1137,12 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
self.assertIsNotNone(f.name)
|
self.assertIsNotNone(f.name)
|
||||||
self.assertEqual(f.newlines, os.linesep)
|
self.assertEqual(f.newlines, os.linesep)
|
||||||
self.assertIsNotNone(f.encoding)
|
self.assertIsNotNone(f.encoding)
|
||||||
|
self.assertIsNotNone(f.errors)
|
||||||
|
|
||||||
def test_text_newline_and_encoding(self):
|
def test_text_newline_and_encoding(self):
|
||||||
f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10,
|
f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10,
|
||||||
newline='', encoding='utf-8')
|
newline='', encoding='utf-8',
|
||||||
|
errors='ignore')
|
||||||
f.write("\u039B\r\n")
|
f.write("\u039B\r\n")
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
self.assertEqual(f.read(), "\u039B\r\n")
|
self.assertEqual(f.read(), "\u039B\r\n")
|
||||||
|
@ -1144,6 +1151,7 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
self.assertIsNone(f.name)
|
self.assertIsNone(f.name)
|
||||||
self.assertIsNone(f.newlines)
|
self.assertIsNone(f.newlines)
|
||||||
self.assertIsNone(f.encoding)
|
self.assertIsNone(f.encoding)
|
||||||
|
self.assertIsNone(f.errors)
|
||||||
|
|
||||||
f.write("\u039B" * 20 + "\r\n")
|
f.write("\u039B" * 20 + "\r\n")
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
@ -1153,6 +1161,7 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
self.assertIsNotNone(f.name)
|
self.assertIsNotNone(f.name)
|
||||||
self.assertIsNotNone(f.newlines)
|
self.assertIsNotNone(f.newlines)
|
||||||
self.assertEqual(f.encoding, 'utf-8')
|
self.assertEqual(f.encoding, 'utf-8')
|
||||||
|
self.assertEqual(f.errors, 'ignore')
|
||||||
|
|
||||||
def test_context_manager_before_rollover(self):
|
def test_context_manager_before_rollover(self):
|
||||||
# A SpooledTemporaryFile can be used as a context manager
|
# A SpooledTemporaryFile can be used as a context manager
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
The file classes in *tempfile* now accept an *errors* parameter that
|
||||||
|
complements the already existing *encoding*. Patch by Stephan Hohe.
|
Loading…
Reference in New Issue