diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-01-01 19:42:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-01 19:42:23 +0200 |
commit | 6dffa67b98f78ae41b596f84478f3379f55d4d03 (patch) | |
tree | 35e822af7c9263229f2071bb24bda6e3a6d62876 | |
parent | [3.8] bpo-39068: Fix race condition in base64 (GH-17627) (GH-24022) (diff) | |
download | cpython-6dffa67b98f78ae41b596f84478f3379f55d4d03.tar.gz cpython-6dffa67b98f78ae41b596f84478f3379f55d4d03.tar.bz2 cpython-6dffa67b98f78ae41b596f84478f3379f55d4d03.zip |
[3.8] bpo-26407: Do not mask errors in csv. (GH-20536) (GH-24021)
Unexpected errors in calling the __iter__ method are no longer
masked by TypeError in csv.reader(), csv.writer.writerow() and
csv.writer.writerows().
(cherry picked from commit c88239f864a27f673c0f0a9e62d2488563f9d081)
-rw-r--r-- | Lib/test/test_csv.py | 20 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst | 3 | ||||
-rw-r--r-- | Modules/_csv.c | 16 |
3 files changed, 30 insertions, 9 deletions
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index a16d14019f3..d421be075ca 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -14,6 +14,12 @@ from itertools import permutations 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 @@ class Test_Csv(unittest.TestCase): 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 @@ class Test_Csv(unittest.TestCase): 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 @@ class Test_Csv(unittest.TestCase): 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 @@ class Test_Csv(unittest.TestCase): 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 00000000000..d0e45cf1b1f --- /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 46d414383cb..069ec9602cc 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -958,8 +958,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; } @@ -1165,10 +1163,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", - seq->ob_type->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. */ @@ -1258,8 +1260,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))) { |