| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9bbb0c5 commit 94306f7
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1122,19 +1122,22 @@ class mydialect(csv.Dialect): | |||
| 1122 | 1122 | with self.assertRaises(csv.Error) as cm: | |
| 1123 | 1123 | mydialect() | |
| 1124 | 1124 | self.assertEqual(str(cm.exception), | |
| 1125 | - '"quotechar" must be a 1-character string') | ||
| 1125 | + '"quotechar" must be a unicode character or None, ' | ||
| 1126 | + 'not a string of length 0') | ||
| 1126 | 1127 | ||
| 1127 | 1128 | mydialect.quotechar = "''" | |
| 1128 | 1129 | with self.assertRaises(csv.Error) as cm: | |
| 1129 | 1130 | mydialect() | |
| 1130 | 1131 | self.assertEqual(str(cm.exception), | |
| 1131 | - '"quotechar" must be a 1-character string') | ||
| 1132 | + '"quotechar" must be a unicode character or None, ' | ||
| 1133 | + 'not a string of length 2') | ||
| 1132 | 1134 | ||
| 1133 | 1135 | mydialect.quotechar = 4 | |
| 1134 | 1136 | with self.assertRaises(csv.Error) as cm: | |
| 1135 | 1137 | mydialect() | |
| 1136 | 1138 | self.assertEqual(str(cm.exception), | |
| 1137 | - '"quotechar" must be string or None, not int') | ||
| 1139 | + '"quotechar" must be a unicode character or None, ' | ||
| 1140 | + 'not int') | ||
| 1138 | 1141 | ||
| 1139 | 1142 | def test_delimiter(self): | |
| 1140 | 1143 | class mydialect(csv.Dialect): | |
@@ -1151,31 +1154,32 @@ class mydialect(csv.Dialect): | |||
| 1151 | 1154 | with self.assertRaises(csv.Error) as cm: | |
| 1152 | 1155 | mydialect() | |
| 1153 | 1156 | self.assertEqual(str(cm.exception), | |
| 1154 | - '"delimiter" must be a 1-character string') | ||
| 1157 | + '"delimiter" must be a unicode character, ' | ||
| 1158 | + 'not a string of length 3') | ||
| 1155 | 1159 | ||
| 1156 | 1160 | mydialect.delimiter = "" | |
| 1157 | 1161 | with self.assertRaises(csv.Error) as cm: | |
| 1158 | 1162 | mydialect() | |
| 1159 | 1163 | self.assertEqual(str(cm.exception), | |
| 1160 | - '"delimiter" must be a 1-character string') | ||
| 1164 | + '"delimiter" must be a unicode character, not a string of length 0') | ||
| 1161 | 1165 | ||
| 1162 | 1166 | mydialect.delimiter = b"," | |
| 1163 | 1167 | with self.assertRaises(csv.Error) as cm: | |
| 1164 | 1168 | mydialect() | |
| 1165 | 1169 | self.assertEqual(str(cm.exception), | |
| 1166 | - '"delimiter" must be string, not bytes') | ||
| 1170 | + '"delimiter" must be a unicode character, not bytes') | ||
| 1167 | 1171 | ||
| 1168 | 1172 | mydialect.delimiter = 4 | |
| 1169 | 1173 | with self.assertRaises(csv.Error) as cm: | |
| 1170 | 1174 | mydialect() | |
| 1171 | 1175 | self.assertEqual(str(cm.exception), | |
| 1172 | - '"delimiter" must be string, not int') | ||
| 1176 | + '"delimiter" must be a unicode character, not int') | ||
| 1173 | 1177 | ||
| 1174 | 1178 | mydialect.delimiter = None | |
| 1175 | 1179 | with self.assertRaises(csv.Error) as cm: | |
| 1176 | 1180 | mydialect() | |
| 1177 | 1181 | self.assertEqual(str(cm.exception), | |
| 1178 | - '"delimiter" must be string, not NoneType') | ||
| 1182 | + '"delimiter" must be a unicode character, not NoneType') | ||
| 1179 | 1183 | ||
| 1180 | 1184 | def test_escapechar(self): | |
| 1181 | 1185 | class mydialect(csv.Dialect): | |
@@ -1189,20 +1193,32 @@ class mydialect(csv.Dialect): | |||
| 1189 | 1193 | self.assertEqual(d.escapechar, "\\") | |
| 1190 | 1194 | ||
| 1191 | 1195 | mydialect.escapechar = "" | |
| 1192 | - with self.assertRaisesRegex(csv.Error, '"escapechar" must be a 1-character string'): | ||
| 1196 | + with self.assertRaises(csv.Error) as cm: | ||
| 1193 | 1197 | mydialect() | |
| 1198 | + self.assertEqual(str(cm.exception), | ||
| 1199 | + '"escapechar" must be a unicode character or None, ' | ||
| 1200 | + 'not a string of length 0') | ||
| 1194 | 1201 | ||
| 1195 | 1202 | mydialect.escapechar = "**" | |
| 1196 | - with self.assertRaisesRegex(csv.Error, '"escapechar" must be a 1-character string'): | ||
| 1203 | + with self.assertRaises(csv.Error) as cm: | ||
| 1197 | 1204 | mydialect() | |
| 1205 | + self.assertEqual(str(cm.exception), | ||
| 1206 | + '"escapechar" must be a unicode character or None, ' | ||
| 1207 | + 'not a string of length 2') | ||
| 1198 | 1208 | ||
| 1199 | 1209 | mydialect.escapechar = b"*" | |
| 1200 | - with self.assertRaisesRegex(csv.Error, '"escapechar" must be string or None, not bytes'): | ||
| 1210 | + with self.assertRaises(csv.Error) as cm: | ||
| 1201 | 1211 | mydialect() | |
| 1212 | + self.assertEqual(str(cm.exception), | ||
| 1213 | + '"escapechar" must be a unicode character or None, ' | ||
| 1214 | + 'not bytes') | ||
| 1202 | 1215 | ||
| 1203 | 1216 | mydialect.escapechar = 4 | |
| 1204 | - with self.assertRaisesRegex(csv.Error, '"escapechar" must be string or None, not int'): | ||
| 1217 | + with self.assertRaises(csv.Error) as cm: | ||
| 1205 | 1218 | mydialect() | |
| 1219 | + self.assertEqual(str(cm.exception), | ||
| 1220 | + '"escapechar" must be a unicode character or None, ' | ||
| 1221 | + 'not int') | ||
| 1206 | 1222 | ||
| 1207 | 1223 | def test_lineterminator(self): | |
| 1208 | 1224 | class mydialect(csv.Dialect): | |
@@ -1223,7 +1239,13 @@ class mydialect(csv.Dialect): | |||
| 1223 | 1239 | with self.assertRaises(csv.Error) as cm: | |
| 1224 | 1240 | mydialect() | |
| 1225 | 1241 | self.assertEqual(str(cm.exception), | |
| 1226 | - '"lineterminator" must be a string') | ||
| 1242 | + '"lineterminator" must be a string, not int') | ||
| 1243 | + | ||
| 1244 | + mydialect.lineterminator = None | ||
| 1245 | + with self.assertRaises(csv.Error) as cm: | ||
| 1246 | + mydialect() | ||
| 1247 | + self.assertEqual(str(cm.exception), | ||
| 1248 | + '"lineterminator" must be a string, not NoneType') | ||
| 1227 | 1249 | ||
| 1228 | 1250 | def test_invalid_chars(self): | |
| 1229 | 1251 | def create_invalid(field_name, value, **kwargs): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + Improve error messages for incorrect types and values of :class:`csv.Dialect` | ||
| 2 | + attributes. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -237,7 +237,7 @@ _set_int(const char *name, int *target, PyObject *src, int dflt) | |||
| 237 | 237 | int value; | |
| 238 | 238 | if (!PyLong_CheckExact(src)) { | |
| 239 | 239 | PyErr_Format(PyExc_TypeError, | |
| 240 | - "\"%s\" must be an integer", name); | ||
| 240 | + "\"%s\" must be an integer, not %T", name, src); | ||
| 241 | 241 | return -1; | |
| 242 | 242 | } | |
| 243 | 243 | value = PyLong_AsInt(src); | |
@@ -255,27 +255,29 @@ _set_char_or_none(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt | |||
| 255 | 255 | if (src == NULL) { | |
| 256 | 256 | *target = dflt; | |
| 257 | 257 | } | |
| 258 | - else { | ||
| 258 | + else if (src == Py_None) { | ||
| 259 | 259 | *target = NOT_SET; | |
| 260 | - if (src != Py_None) { | ||
| 261 | - if (!PyUnicode_Check(src)) { | ||
| 262 | - PyErr_Format(PyExc_TypeError, | ||
| 263 | - "\"%s\" must be string or None, not %.200s", name, | ||
| 264 | - Py_TYPE(src)->tp_name); | ||
| 265 | - return -1; | ||
| 266 | - } | ||
| 267 | - Py_ssize_t len = PyUnicode_GetLength(src); | ||
| 268 | - if (len < 0) { | ||
| 269 | - return -1; | ||
| 270 | - } | ||
| 271 | - if (len != 1) { | ||
| 272 | - PyErr_Format(PyExc_TypeError, | ||
| 273 | - "\"%s\" must be a 1-character string", | ||
| 274 | - name); | ||
| 275 | - return -1; | ||
| 276 | - } | ||
| 277 | - *target = PyUnicode_READ_CHAR(src, 0); | ||
| 260 | + } | ||
| 261 | + else { | ||
| 262 | + // similar to PyArg_Parse("C?") | ||
| 263 | + if (!PyUnicode_Check(src)) { | ||
| 264 | + PyErr_Format(PyExc_TypeError, | ||
| 265 | + "\"%s\" must be a unicode character or None, not %T", | ||
| 266 | + name, src); | ||
| 267 | + return -1; | ||
| 268 | + } | ||
| 269 | + Py_ssize_t len = PyUnicode_GetLength(src); | ||
| 270 | + if (len < 0) { | ||
| 271 | + return -1; | ||
| 278 | 272 | } | |
| 273 | + if (len != 1) { | ||
| 274 | + PyErr_Format(PyExc_TypeError, | ||
| 275 | + "\"%s\" must be a unicode character or None, " | ||
| 276 | + "not a string of length %zd", | ||
| 277 | + name, len); | ||
| 278 | + return -1; | ||
| 279 | + } | ||
| 280 | + *target = PyUnicode_READ_CHAR(src, 0); | ||
| 279 | 281 | } | |
| 280 | 282 | return 0; | |
| 281 | 283 | } | |
@@ -287,20 +289,22 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) | |||
| 287 | 289 | *target = dflt; | |
| 288 | 290 | } | |
| 289 | 291 | else { | |
| 292 | + // similar to PyArg_Parse("C") | ||
| 290 | 293 | if (!PyUnicode_Check(src)) { | |
| 291 | 294 | PyErr_Format(PyExc_TypeError, | |
| 292 | - "\"%s\" must be string, not %.200s", name, | ||
| 293 | - Py_TYPE(src)->tp_name); | ||
| 294 | - return -1; | ||
| 295 | + "\"%s\" must be a unicode character, not %T", | ||
| 296 | + name, src); | ||
| 297 | + return -1; | ||
| 295 | 298 | } | |
| 296 | 299 | Py_ssize_t len = PyUnicode_GetLength(src); | |
| 297 | 300 | if (len < 0) { | |
| 298 | 301 | return -1; | |
| 299 | 302 | } | |
| 300 | 303 | if (len != 1) { | |
| 301 | 304 | PyErr_Format(PyExc_TypeError, | |
| 302 | - "\"%s\" must be a 1-character string", | ||
| 303 | - name); | ||
| 305 | + "\"%s\" must be a unicode character, " | ||
| 306 | + "not a string of length %zd", | ||
| 307 | + name, len); | ||
| 304 | 308 | return -1; | |
| 305 | 309 | } | |
| 306 | 310 | *target = PyUnicode_READ_CHAR(src, 0); | |
@@ -314,16 +318,12 @@ _set_str(const char *name, PyObject **target, PyObject *src, const char *dflt) | |||
| 314 | 318 | if (src == NULL) | |
| 315 | 319 | *target = PyUnicode_DecodeASCII(dflt, strlen(dflt), NULL); | |
| 316 | 320 | else { | |
| 317 | - if (src == Py_None) | ||
| 318 | - *target = NULL; | ||
| 319 | - else if (!PyUnicode_Check(src)) { | ||
| 321 | + if (!PyUnicode_Check(src)) { | ||
| 320 | 322 | PyErr_Format(PyExc_TypeError, | |
| 321 | - "\"%s\" must be a string", name); | ||
| 323 | + "\"%s\" must be a string, not %T", name, src); | ||
| 322 | 324 | return -1; | |
| 323 | 325 | } | |
| 324 | - else { | ||
| 325 | - Py_XSETREF(*target, Py_NewRef(src)); | ||
| 326 | - } | ||
| 326 | + Py_XSETREF(*target, Py_NewRef(src)); | ||
| 327 | 327 | } | |
| 328 | 328 | return 0; | |
| 329 | 329 | } | |
@@ -533,22 +533,13 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) | |||
| 533 | 533 | /* validate options */ | |
| 534 | 534 | if (dialect_check_quoting(self->quoting)) | |
| 535 | 535 | goto err; | |
| 536 | - if (self->delimiter == NOT_SET) { | ||
| 537 | - PyErr_SetString(PyExc_TypeError, | ||
| 538 | - "\"delimiter\" must be a 1-character string"); | ||
| 539 | - goto err; | ||
| 540 | - } | ||
| 541 | 536 | if (quotechar == Py_None && quoting == NULL) | |
| 542 | 537 | self->quoting = QUOTE_NONE; | |
| 543 | 538 | if (self->quoting != QUOTE_NONE && self->quotechar == NOT_SET) { | |
| 544 | 539 | PyErr_SetString(PyExc_TypeError, | |
| 545 | 540 | "quotechar must be set if quoting enabled"); | |
| 546 | 541 | goto err; | |
| 547 | 542 | } | |
| 548 | - if (self->lineterminator == NULL) { | ||
| 549 | - PyErr_SetString(PyExc_TypeError, "lineterminator must be set"); | ||
| 550 | - goto err; | ||
| 551 | - } | ||
| 552 | 543 | if (dialect_check_char("delimiter", self->delimiter, self, true) || | |
| 553 | 544 | dialect_check_char("escapechar", self->escapechar, self, | |
| 554 | 545 | !self->skipinitialspace) || | |
| Back | FazBrowse Home | New Git URL |
0 commit comments