summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-01-01 19:42:23 +0200
committerGitHub <noreply@github.com>2021-01-01 19:42:23 +0200
commit6dffa67b98f78ae41b596f84478f3379f55d4d03 (patch)
tree35e822af7c9263229f2071bb24bda6e3a6d62876
parent[3.8] bpo-39068: Fix race condition in base64 (GH-17627) (GH-24022) (diff)
downloadcpython-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.py20
-rw-r--r--Misc/NEWS.d/next/Library/2020-05-30-14-19-47.bpo-26407.MjWLO1.rst3
-rw-r--r--Modules/_csv.c16
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))) {