Issue #18829: csv.Dialect() now checks type for delimiter, escapechar and

quotechar fields.  Original patch by Vajrasky Kok.
This commit is contained in:
Serhiy Storchaka 2013-12-19 16:27:18 +02:00
parent 800e11b406
commit cac23a50ee
3 changed files with 50 additions and 6 deletions

View File

@ -747,6 +747,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)
@ -755,12 +756,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):
@ -771,12 +781,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):
@ -787,12 +816,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):

View File

@ -29,6 +29,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.

View File

@ -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)