diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2013-12-19 14:28:04 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2013-12-19 14:28:04 (GMT) |
commit | cf58fb5e2947ebe6ac1e06b7f8fbe9a417b7430f (patch) | |
tree | dd05fec470e5b75a4a79c6e5fb89e45048c66617 | |
parent | 5272fa9c5707b3cdcd6f49fdaf595b21bec6b2bd (diff) | |
parent | cac23a50ee2979b8c2e3472e6b13efb1a8bd4f78 (diff) | |
download | cpython-cf58fb5e2947ebe6ac1e06b7f8fbe9a417b7430f.zip cpython-cf58fb5e2947ebe6ac1e06b7f8fbe9a417b7430f.tar.gz cpython-cf58fb5e2947ebe6ac1e06b7f8fbe9a417b7430f.tar.bz2 |
Issue #18829: csv.Dialect() now checks type for delimiter, escapechar and
quotechar fields. Original patch by Vajrasky Kok.
-rw-r--r-- | Lib/test/test_csv.py | 44 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/_csv.c | 9 |
3 files changed, 50 insertions, 6 deletions
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 01fba21..cbde781 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -756,6 +756,7 @@ class TestDialectValidity(unittest.TestCase): lineterminator = '\r\n' quoting = csv.QUOTE_NONE d = mydialect() + self.assertEqual(d.quoting, csv.QUOTE_NONE) mydialect.quoting = None self.assertRaises(csv.Error, mydialect) @@ -764,12 +765,21 @@ class TestDialectValidity(unittest.TestCase): mydialect.quoting = csv.QUOTE_ALL mydialect.quotechar = '"' d = mydialect() + self.assertEqual(d.quoting, csv.QUOTE_ALL) + self.assertEqual(d.quotechar, '"') + self.assertTrue(d.doublequote) mydialect.quotechar = "''" - self.assertRaises(csv.Error, mydialect) + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"quotechar" must be an 1-character string') mydialect.quotechar = 4 - self.assertRaises(csv.Error, mydialect) + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"quotechar" must be string, not int') def test_delimiter(self): class mydialect(csv.Dialect): @@ -780,12 +790,31 @@ class TestDialectValidity(unittest.TestCase): lineterminator = '\r\n' quoting = csv.QUOTE_NONE d = mydialect() + self.assertEqual(d.delimiter, ";") mydialect.delimiter = ":::" - self.assertRaises(csv.Error, mydialect) + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"delimiter" must be an 1-character string') + + mydialect.delimiter = "" + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"delimiter" must be an 1-character string') + + mydialect.delimiter = b"," + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"delimiter" must be string, not bytes') mydialect.delimiter = 4 - self.assertRaises(csv.Error, mydialect) + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"delimiter" must be string, not int') def test_lineterminator(self): class mydialect(csv.Dialect): @@ -796,12 +825,17 @@ class TestDialectValidity(unittest.TestCase): lineterminator = '\r\n' quoting = csv.QUOTE_NONE d = mydialect() + self.assertEqual(d.lineterminator, '\r\n') mydialect.lineterminator = ":::" d = mydialect() + self.assertEqual(d.lineterminator, ":::") mydialect.lineterminator = 4 - self.assertRaises(csv.Error, mydialect) + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"lineterminator" must be a string') class TestSniffer(unittest.TestCase): @@ -44,6 +44,9 @@ Core and Builtins Library ------- +- Issue #18829: csv.Dialect() now checks type for delimiter, escapechar and + quotechar fields. Original patch by Vajrasky Kok. + - Issue #19855: uuid.getnode() on Unix now looks on the PATH for the executables used to find the mac address, with /sbin and /usr/sbin as fallbacks. diff --git a/Modules/_csv.c b/Modules/_csv.c index 183a9a5..c8767d1 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -239,6 +239,12 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) *target = '\0'; if (src != Py_None) { Py_ssize_t len; + if (!PyUnicode_Check(src)) { + PyErr_Format(PyExc_TypeError, + "\"%s\" must be string, not %.200s", name, + src->ob_type->tp_name); + return -1; + } len = PyUnicode_GetLength(src); if (len > 1) { PyErr_Format(PyExc_TypeError, @@ -425,7 +431,8 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (dialect_check_quoting(self->quoting)) goto err; if (self->delimiter == 0) { - PyErr_SetString(PyExc_TypeError, "delimiter must be set"); + PyErr_SetString(PyExc_TypeError, + "\"delimiter\" must be an 1-character string"); goto err; } if (quotechar == Py_None && quoting == NULL) |