Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cac23a5

Browse files
Issue #18829: csv.Dialect() now checks type for delimiter, escapechar and
quotechar fields. Original patch by Vajrasky Kok.
1 parent 800e11b commit cac23a5

3 files changed

Lines changed: 50 additions & 6 deletions

File tree

Lib/test/test_csv.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ class mydialect(csv.Dialect):
747747
lineterminator = '\r\n'
748748
quoting = csv.QUOTE_NONE
749749
d = mydialect()
750+
self.assertEqual(d.quoting, csv.QUOTE_NONE)
750751

751752
mydialect.quoting = None
752753
self.assertRaises(csv.Error, mydialect)
@@ -755,12 +756,21 @@ class mydialect(csv.Dialect):
755756
mydialect.quoting = csv.QUOTE_ALL
756757
mydialect.quotechar = '"'
757758
d = mydialect()
759+
self.assertEqual(d.quoting, csv.QUOTE_ALL)
760+
self.assertEqual(d.quotechar, '"')
761+
self.assertTrue(d.doublequote)
758762

759763
mydialect.quotechar = "''"
760-
self.assertRaises(csv.Error, mydialect)
764+
with self.assertRaises(csv.Error) as cm:
765+
mydialect()
766+
self.assertEqual(str(cm.exception),
767+
'"quotechar" must be an 1-character string')
761768

762769
mydialect.quotechar = 4
763-
self.assertRaises(csv.Error, mydialect)
770+
with self.assertRaises(csv.Error) as cm:
771+
mydialect()
772+
self.assertEqual(str(cm.exception),
773+
'"quotechar" must be string, not int')
764774

765775
def test_delimiter(self):
766776
class mydialect(csv.Dialect):
@@ -771,12 +781,31 @@ class mydialect(csv.Dialect):
771781
lineterminator = '\r\n'
772782
quoting = csv.QUOTE_NONE
773783
d = mydialect()
784+
self.assertEqual(d.delimiter, ";")
774785

775786
mydialect.delimiter = ":::"
776-
self.assertRaises(csv.Error, mydialect)
787+
with self.assertRaises(csv.Error) as cm:
788+
mydialect()
789+
self.assertEqual(str(cm.exception),
790+
'"delimiter" must be an 1-character string')
791+
792+
mydialect.delimiter = ""
793+
with self.assertRaises(csv.Error) as cm:
794+
mydialect()
795+
self.assertEqual(str(cm.exception),
796+
'"delimiter" must be an 1-character string')
797+
798+
mydialect.delimiter = b","
799+
with self.assertRaises(csv.Error) as cm:
800+
mydialect()
801+
self.assertEqual(str(cm.exception),
802+
'"delimiter" must be string, not bytes')
777803

778804
mydialect.delimiter = 4
779-
self.assertRaises(csv.Error, mydialect)
805+
with self.assertRaises(csv.Error) as cm:
806+
mydialect()
807+
self.assertEqual(str(cm.exception),
808+
'"delimiter" must be string, not int')
780809

781810
def test_lineterminator(self):
782811
class mydialect(csv.Dialect):
@@ -787,12 +816,17 @@ class mydialect(csv.Dialect):
787816
lineterminator = '\r\n'
788817
quoting = csv.QUOTE_NONE
789818
d = mydialect()
819+
self.assertEqual(d.lineterminator, '\r\n')
790820

791821
mydialect.lineterminator = ":::"
792822
d = mydialect()
823+
self.assertEqual(d.lineterminator, ":::")
793824

794825
mydialect.lineterminator = 4
795-
self.assertRaises(csv.Error, mydialect)
826+
with self.assertRaises(csv.Error) as cm:
827+
mydialect()
828+
self.assertEqual(str(cm.exception),
829+
'"lineterminator" must be a string')
796830

797831

798832
class TestSniffer(unittest.TestCase):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ Core and Builtins
2929
Library
3030
-------
3131

32+
- Issue #18829: csv.Dialect() now checks type for delimiter, escapechar and
33+
quotechar fields. Original patch by Vajrasky Kok.
34+
3235
- Issue #19855: uuid.getnode() on Unix now looks on the PATH for the
3336
executables used to find the mac address, with /sbin and /usr/sbin as
3437
fallbacks.

Modules/_csv.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
239239
*target = '\0';
240240
if (src != Py_None) {
241241
Py_ssize_t len;
242+
if (!PyUnicode_Check(src)) {
243+
PyErr_Format(PyExc_TypeError,
244+
"\"%s\" must be string, not %.200s", name,
245+
src->ob_type->tp_name);
246+
return -1;
247+
}
242248
len = PyUnicode_GetLength(src);
243249
if (len > 1) {
244250
PyErr_Format(PyExc_TypeError,
@@ -425,7 +431,8 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
425431
if (dialect_check_quoting(self->quoting))
426432
goto err;
427433
if (self->delimiter == 0) {
428-
PyErr_SetString(PyExc_TypeError, "delimiter must be set");
434+
PyErr_SetString(PyExc_TypeError,
435+
"\"delimiter\" must be an 1-character string");
429436
goto err;
430437
}
431438
if (quotechar == Py_None && quoting == NULL)

0 commit comments

Comments
 (0)