[Python-checkins] bpo-27300: Add the errors parameter to tempfile classes. (GH-6696)

Serhiy Storchaka webhook-mailer at python.org
Wed May 23 01:07:11 EDT 2018


https://github.com/python/cpython/commit/825aab95fde959541859383f8ea7e7854ebfd49f
commit: 825aab95fde959541859383f8ea7e7854ebfd49f
branch: master
author: sth <sth.dev at tejp.de>
committer: Serhiy Storchaka <storchaka at gmail.com>
date: 2018-05-23T08:07:01+03:00
summary:

bpo-27300: Add the errors parameter to tempfile classes. (GH-6696)

files:
A Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst
M Doc/library/tempfile.rst
M Lib/tempfile.py
M Lib/test/test_tempfile.py

diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst
index c59aca1e1890..79914e15f444 100644
--- a/Doc/library/tempfile.rst
+++ b/Doc/library/tempfile.rst
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
 
diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index 214322416963..e6fb3c8e9ad8 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -519,7 +519,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.
@@ -528,6 +528,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
@@ -547,7 +548,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:
@@ -568,7 +569,7 @@ 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.
@@ -576,6 +577,7 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
         '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
@@ -609,7 +611,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
@@ -619,7 +622,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
@@ -633,7 +636,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:
@@ -646,7 +649,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
@@ -692,12 +695,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()
@@ -725,12 +727,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)
diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py
index 710756bde64c..e5098d2eea6b 100644
--- a/Lib/test/test_tempfile.py
+++ b/Lib/test/test_tempfile.py
@@ -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)
@@ -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
@@ -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)
@@ -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")
@@ -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)
@@ -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
diff --git a/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst b/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst
new file mode 100644
index 000000000000..5edbc86b9c9c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst
@@ -0,0 +1,2 @@
+The file classes in *tempfile* now accept an *errors* parameter that
+complements the already existing *encoding*.  Patch by Stephan Hohe.



More information about the Python-checkins mailing list