Skip to content

Commit 611fb4f

Browse files
committed
bpo-20028: Address code review
1 parent 85a418d commit 611fb4f

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed

Lib/test/test_csv.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,12 @@ class mydialect(csv.Dialect):
940940
self.assertEqual(str(cm.exception),
941941
'"delimiter" must be string, not int')
942942

943+
mydialect.delimiter = None
944+
with self.assertRaises(csv.Error) as cm:
945+
mydialect()
946+
self.assertEqual(str(cm.exception),
947+
'"delimiter" must be string, not NoneType')
948+
943949
def test_escapechar(self):
944950
class mydialect(csv.Dialect):
945951
delimiter = ";"

Modules/_csv.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,28 +229,21 @@ _set_int(const char *name, int *target, PyObject *src, int dflt)
229229
}
230230

231231
static int
232-
_set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
232+
_set_char_or_none(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
233233
{
234-
if (src == NULL)
234+
if (src == NULL) {
235235
*target = dflt;
236+
}
236237
else {
237238
*target = '\0';
238239
if (src != Py_None) {
239-
Py_ssize_t len;
240240
if (!PyUnicode_Check(src)) {
241-
if (strcmp(name, "delimiter") == 0) {
242-
PyErr_Format(PyExc_TypeError,
243-
"\"%s\" must be string, not %.200s", name,
244-
Py_TYPE(src)->tp_name);
245-
}
246-
else {
247-
PyErr_Format(PyExc_TypeError,
248-
"\"%s\" must be string or None, not %.200s", name,
249-
Py_TYPE(src)->tp_name);
250-
}
241+
PyErr_Format(PyExc_TypeError,
242+
"\"%s\" must be string or None, not %.200s", name,
243+
Py_TYPE(src)->tp_name);
251244
return -1;
252245
}
253-
len = PyUnicode_GetLength(src);
246+
Py_ssize_t len = PyUnicode_GetLength(src);
254247
if (len != 1) {
255248
PyErr_Format(PyExc_TypeError,
256249
"\"%s\" must be a 1-character string",
@@ -266,6 +259,35 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
266259
return 0;
267260
}
268261

262+
static int
263+
_set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
264+
{
265+
if (src == NULL) {
266+
*target = dflt;
267+
}
268+
else {
269+
*target = '\0';
270+
if (!PyUnicode_Check(src)) {
271+
PyErr_Format(PyExc_TypeError,
272+
"\"%s\" must be string, not %.200s", name,
273+
Py_TYPE(src)->tp_name);
274+
return -1;
275+
}
276+
Py_ssize_t len = PyUnicode_GetLength(src);
277+
if (len != 1) {
278+
PyErr_Format(PyExc_TypeError,
279+
"\"%s\" must be a 1-character string",
280+
name);
281+
return -1;
282+
}
283+
/* PyUnicode_READY() is called in PyUnicode_GetLength() */
284+
else {
285+
*target = PyUnicode_READ_CHAR(src, 0);
286+
}
287+
}
288+
return 0;
289+
}
290+
269291
static int
270292
_set_str(const char *name, PyObject **target, PyObject *src, const char *dflt)
271293
{
@@ -453,9 +475,9 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
453475
goto err
454476
DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ',');
455477
DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, true);
456-
DIASET(_set_char, "escapechar", &self->escapechar, escapechar, 0);
478+
DIASET(_set_char_or_none, "escapechar", &self->escapechar, escapechar, 0);
457479
DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n");
458-
DIASET(_set_char, "quotechar", &self->quotechar, quotechar, '"');
480+
DIASET(_set_char_or_none, "quotechar", &self->quotechar, quotechar, '"');
459481
DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL);
460482
DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, false);
461483
DIASET(_set_bool, "strict", &self->strict, strict, false);

0 commit comments

Comments
 (0)