diff -r cecec75c2250 Lib/csv.py --- a/Lib/csv.py Thu Sep 05 16:06:46 2013 +0200 +++ b/Lib/csv.py Thu Sep 05 22:36:59 2013 +0800 @@ -46,7 +46,7 @@ def _validate(self): try: _Dialect(self) - except TypeError as e: + except (TypeError, ValueError) as e: # We do this for compatibility with py2.3 raise Error(str(e)) diff -r cecec75c2250 Lib/test/test_csv.py --- a/Lib/test/test_csv.py Thu Sep 05 16:06:46 2013 +0200 +++ b/Lib/test/test_csv.py Thu Sep 05 22:36:59 2013 +0800 @@ -22,7 +22,7 @@ self.assertRaises(TypeError, ctor, None) self.assertRaises(TypeError, ctor, arg, bad_attr = 0) self.assertRaises(TypeError, ctor, arg, delimiter = 0) - self.assertRaises(TypeError, ctor, arg, delimiter = 'XX') + self.assertRaises(ValueError, ctor, arg, delimiter = 'XX') self.assertRaises(csv.Error, ctor, arg, 'foo') self.assertRaises(TypeError, ctor, arg, delimiter=None) self.assertRaises(TypeError, ctor, arg, delimiter=1) @@ -743,7 +743,7 @@ skipinitialspace = True lineterminator = '\r\n' quoting = csv.QUOTE_NONE - d = mydialect() + mydialect() mydialect.quoting = None self.assertRaises(csv.Error, mydialect) @@ -751,13 +751,19 @@ mydialect.doublequote = True mydialect.quoting = csv.QUOTE_ALL mydialect.quotechar = '"' - d = mydialect() + mydialect() 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): @@ -767,13 +773,25 @@ skipinitialspace = True lineterminator = '\r\n' quoting = csv.QUOTE_NONE - d = mydialect() + mydialect() 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 = 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): @@ -783,13 +801,16 @@ skipinitialspace = True lineterminator = '\r\n' quoting = csv.QUOTE_NONE - d = mydialect() + mydialect() mydialect.lineterminator = ":::" - d = mydialect() + mydialect() 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): diff -r cecec75c2250 Modules/_csv.c --- a/Modules/_csv.c Thu Sep 05 16:06:46 2013 +0200 +++ b/Modules/_csv.c Thu Sep 05 22:36:59 2013 +0800 @@ -239,11 +239,16 @@ *target = '\0'; if (src != Py_None) { Py_ssize_t len; + if (!PyUnicode_Check(src)) { + PyErr_Format(PyExc_TypeError, + "\"%s\" must be string, not %s", name, + src->ob_type->tp_name); + return -1; + } len = PyUnicode_GetLength(src); if (len > 1) { - PyErr_Format(PyExc_TypeError, - "\"%s\" must be an 1-character string", - name); + PyErr_Format(PyExc_ValueError, + "\"%s\" must be an 1-character string", name); return -1; } /* PyUnicode_READY() is called in PyUnicode_GetLength() */