bpo-20028: Empty escapechar/quotechar is not allowed for csv.Dialect (GH-28833)

This commit is contained in:
Dong-hee Na 2021-10-11 20:08:15 +09:00 committed by GitHub
parent d74da9e140
commit ab62051152
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 10 deletions

View file

@ -383,6 +383,8 @@ Dialects support the following attributes:
:const:`False`. On reading, the *escapechar* removes any special meaning from
the following character. It defaults to :const:`None`, which disables escaping.
.. versionchanged:: 3.11
An empty *escapechar* is not allowed.
.. attribute:: Dialect.lineterminator
@ -402,6 +404,8 @@ Dialects support the following attributes:
as the *delimiter* or *quotechar*, or which contain new-line characters. It
defaults to ``'"'``.
.. versionchanged:: 3.11
An empty *quotechar* is not allowed.
.. attribute:: Dialect.quoting

View file

@ -44,6 +44,8 @@ def _test_arg_valid(self, ctor, arg):
quoting=csv.QUOTE_ALL, quotechar='')
self.assertRaises(TypeError, ctor, arg,
quoting=csv.QUOTE_ALL, quotechar=None)
self.assertRaises(TypeError, ctor, arg,
quoting=csv.QUOTE_NONE, quotechar='')
def test_reader_arg_valid(self):
self._test_arg_valid(csv.reader, [])
@ -342,7 +344,6 @@ def test_read_escape(self):
self._read_test(['a,^b,c'], [['a', 'b', 'c']], escapechar='^')
self._read_test(['a,\0b,c'], [['a', 'b', 'c']], escapechar='\0')
self._read_test(['a,\\b,c'], [['a', '\\b', 'c']], escapechar=None)
self._read_test(['a,\\b,c'], [['a', '\\b', 'c']], escapechar='')
self._read_test(['a,\\b,c'], [['a', '\\b', 'c']])
def test_read_quoting(self):
@ -913,6 +914,12 @@ class mydialect(csv.Dialect):
self.assertEqual(d.quotechar, '"')
self.assertTrue(d.doublequote)
mydialect.quotechar = ""
with self.assertRaises(csv.Error) as cm:
mydialect()
self.assertEqual(str(cm.exception),
'"quotechar" must be a 1-character string')
mydialect.quotechar = "''"
with self.assertRaises(csv.Error) as cm:
mydialect()
@ -977,6 +984,10 @@ class mydialect(csv.Dialect):
d = mydialect()
self.assertEqual(d.escapechar, "\\")
mydialect.escapechar = ""
with self.assertRaisesRegex(csv.Error, '"escapechar" must be a 1-character string'):
mydialect()
mydialect.escapechar = "**"
with self.assertRaisesRegex(csv.Error, '"escapechar" must be a 1-character string'):
mydialect()

View file

@ -0,0 +1,2 @@
Empty escapechar/quotechar is not allowed when initializing
:class:`csv.Dialect`. Patch by Vajrasky Kok and Dong-hee Na.

View file

@ -250,16 +250,14 @@ _set_char_or_none(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt
if (len < 0) {
return -1;
}
if (len > 1) {
if (len != 1) {
PyErr_Format(PyExc_TypeError,
"\"%s\" must be a 1-character string",
name);
return -1;
}
/* PyUnicode_READY() is called in PyUnicode_GetLength() */
else if (len > 0) {
*target = PyUnicode_READ_CHAR(src, 0);
}
*target = PyUnicode_READ_CHAR(src, 0);
}
}
return 0;
@ -272,7 +270,6 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
*target = dflt;
}
else {
*target = NOT_SET;
if (!PyUnicode_Check(src)) {
PyErr_Format(PyExc_TypeError,
"\"%s\" must be string, not %.200s", name,
@ -283,16 +280,14 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
if (len < 0) {
return -1;
}
if (len > 1) {
if (len != 1) {
PyErr_Format(PyExc_TypeError,
"\"%s\" must be a 1-character string",
name);
return -1;
}
/* PyUnicode_READY() is called in PyUnicode_GetLength() */
else if (len > 0) {
*target = PyUnicode_READ_CHAR(src, 0);
}
*target = PyUnicode_READ_CHAR(src, 0);
}
return 0;
}