[Python-checkins] bpo-26407: Do not mask errors in csv. (GH-20536)

Serhiy Storchaka webhook-mailer at python.org
Mon Jun 22 04:22:08 EDT 2020


https://github.com/python/cpython/commit/c88239f864a27f673c0f0a9e62d2488563f9d081
commit: c88239f864a27f673c0f0a9e62d2488563f9d081
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-22T11:21:59+03:00
summary:

bpo-26407: Do not mask errors in csv. (GH-20536)

Unexpected errors in calling the __iter__ method are no longer
masked by TypeError in csv.reader(), csv.writer.writerow() and
csv.writer.writerows().

files:
A Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst
M Lib/test/test_csv.py
M Modules/_csv.c

diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index a16d14019f341..d421be075ca27 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -14,6 +14,12 @@
 from textwrap import dedent
 from collections import OrderedDict
 
+
+class BadIterable:
+    def __iter__(self):
+        raise OSError
+
+
 class Test_Csv(unittest.TestCase):
     """
     Test the underlying C csv parser in ways that are not appropriate
@@ -40,9 +46,15 @@ def _test_arg_valid(self, ctor, arg):
 
     def test_reader_arg_valid(self):
         self._test_arg_valid(csv.reader, [])
+        self.assertRaises(OSError, csv.reader, BadIterable())
 
     def test_writer_arg_valid(self):
         self._test_arg_valid(csv.writer, StringIO())
+        class BadWriter:
+            @property
+            def write(self):
+                raise OSError
+        self.assertRaises(OSError, csv.writer, BadWriter())
 
     def _test_default_attrs(self, ctor, *args):
         obj = ctor(*args)
@@ -141,6 +153,7 @@ def test_write_arg_valid(self):
         self._write_test([None], '""')
         self._write_error_test(csv.Error, [None], quoting = csv.QUOTE_NONE)
         # Check that exceptions are passed up the chain
+        self._write_error_test(OSError, BadIterable())
         class BadList:
             def __len__(self):
                 return 10;
@@ -230,6 +243,12 @@ def test_writerows_with_none(self):
             fileobj.seek(0)
             self.assertEqual(fileobj.read(), 'a\r\n""\r\n')
 
+    def test_writerows_errors(self):
+        with TemporaryFile("w+", newline='') as fileobj:
+            writer = csv.writer(fileobj)
+            self.assertRaises(TypeError, writer.writerows, None)
+            self.assertRaises(OSError, writer.writerows, BadIterable())
+
     @support.cpython_only
     def test_writerows_legacy_strings(self):
         import _testcapi
@@ -334,7 +353,6 @@ def test_read_linenum(self):
     def test_roundtrip_quoteed_newlines(self):
         with TemporaryFile("w+", newline='') as fileobj:
             writer = csv.writer(fileobj)
-            self.assertRaises(TypeError, writer.writerows, None)
             rows = [['a\nb','b'],['c','x\r\nd']]
             writer.writerows(rows)
             fileobj.seek(0)
diff --git a/Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst b/Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst
new file mode 100644
index 0000000000000..d0e45cf1b1f2f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst
@@ -0,0 +1,3 @@
+Unexpected errors in calling the ``__iter__`` method are no longer masked
+by ``TypeError`` in :func:`csv.reader`, :func:`csv.writer.writerow` and
+:meth:`csv.writer.writerows`.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 2d4247740eb29..da61db9377f94 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -956,8 +956,6 @@ csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args)
     }
     self->input_iter = PyObject_GetIter(iterator);
     if (self->input_iter == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                        "argument 1 must be an iterator");
         Py_DECREF(self);
         return NULL;
     }
@@ -1163,10 +1161,14 @@ csv_writerow(WriterObj *self, PyObject *seq)
     PyObject *iter, *field, *line, *result;
 
     iter = PyObject_GetIter(seq);
-    if (iter == NULL)
-        return PyErr_Format(_csvstate_global->error_obj,
-                            "iterable expected, not %.200s",
-                            Py_TYPE(seq)->tp_name);
+    if (iter == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            PyErr_Format(_csvstate_global->error_obj,
+                         "iterable expected, not %.200s",
+                         Py_TYPE(seq)->tp_name);
+        }
+        return NULL;
+    }
 
     /* Join all fields in internal buffer.
      */
@@ -1256,8 +1258,6 @@ csv_writerows(WriterObj *self, PyObject *seqseq)
 
     row_iter = PyObject_GetIter(seqseq);
     if (row_iter == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                        "writerows() argument must be iterable");
         return NULL;
     }
     while ((row_obj = PyIter_Next(row_iter))) {



More information about the Python-checkins mailing list