blob: c61519af7a783779e3d6e8cf8ed26e4cb8cb2db6 [file] [log] [blame]
Skip Montanaroa16b21f2003-03-23 14:32:54 +00001/* csv module */
2
3/*
4
5This module provides the low-level underpinnings of a CSV reading/writing
6module. Users should not use this module directly, but import the csv.py
7module instead.
8
9**** For people modifying this code, please note that as of this writing
Skip Montanarodfa35fa2003-04-11 21:40:01 +000010**** (2003-03-23), it is intended that this code should work with Python
Skip Montanaroa16b21f2003-03-23 14:32:54 +000011**** 2.2.
12
Skip Montanarob4a04172003-03-20 23:29:12 +000013*/
14
15#include "Python.h"
16#include "structmember.h"
17
Skip Montanaroa16b21f2003-03-23 14:32:54 +000018
Skip Montanarob4a04172003-03-20 23:29:12 +000019/* begin 2.2 compatibility macros */
20#ifndef PyDoc_STRVAR
21/* Define macros for inline documentation. */
22#define PyDoc_VAR(name) static char name[]
23#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
24#ifdef WITH_DOC_STRINGS
25#define PyDoc_STR(str) str
26#else
27#define PyDoc_STR(str) ""
28#endif
29#endif /* ifndef PyDoc_STRVAR */
30
31#ifndef PyMODINIT_FUNC
32# if defined(__cplusplus)
33# define PyMODINIT_FUNC extern "C" void
34# else /* __cplusplus */
35# define PyMODINIT_FUNC void
36# endif /* __cplusplus */
37#endif
38/* end 2.2 compatibility macros */
39
40static PyObject *error_obj; /* CSV exception */
41static PyObject *dialects; /* Dialect registry */
42
43typedef enum {
44 START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
45 IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD
46} ParserState;
47
48typedef enum {
49 QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE
50} QuoteStyle;
51
52typedef struct {
53 QuoteStyle style;
54 char *name;
55} StyleDesc;
56
57static StyleDesc quote_styles[] = {
58 { QUOTE_MINIMAL, "QUOTE_MINIMAL" },
59 { QUOTE_ALL, "QUOTE_ALL" },
60 { QUOTE_NONNUMERIC, "QUOTE_NONNUMERIC" },
61 { QUOTE_NONE, "QUOTE_NONE" },
62 { 0 }
63};
64
65typedef struct {
66 PyObject_HEAD
67
68 int doublequote; /* is " represented by ""? */
69 char delimiter; /* field separator */
70 char quotechar; /* quote character */
71 char escapechar; /* escape character */
72 int skipinitialspace; /* ignore spaces following delimiter? */
73 PyObject *lineterminator; /* string to write between records */
74 QuoteStyle quoting; /* style of quoting to write */
75
76 int strict; /* raise exception on bad CSV */
77} DialectObj;
78
79staticforward PyTypeObject Dialect_Type;
80
81typedef struct {
82 PyObject_HEAD
83
84 PyObject *input_iter; /* iterate over this for input lines */
85
86 DialectObj *dialect; /* parsing dialect */
87
88 PyObject *fields; /* field list for current record */
89 ParserState state; /* current CSV parse state */
90 char *field; /* build current field in here */
91 int field_size; /* size of allocated buffer */
92 int field_len; /* length of current field */
93 int had_parse_error; /* did we have a parse error? */
94} ReaderObj;
95
96staticforward PyTypeObject Reader_Type;
97
98#define ReaderObject_Check(v) ((v)->ob_type == &Reader_Type)
99
100typedef struct {
101 PyObject_HEAD
102
103 PyObject *writeline; /* write output lines to this file */
104
105 DialectObj *dialect; /* parsing dialect */
106
107 char *rec; /* buffer for parser.join */
108 int rec_size; /* size of allocated record */
109 int rec_len; /* length of record */
110 int num_fields; /* number of fields in record */
111} WriterObj;
112
113staticforward PyTypeObject Writer_Type;
114
115/*
116 * DIALECT class
117 */
118
119static PyObject *
120get_dialect_from_registry(PyObject * name_obj)
121{
122 PyObject *dialect_obj;
123
124 dialect_obj = PyDict_GetItem(dialects, name_obj);
125 if (dialect_obj == NULL)
126 return PyErr_Format(error_obj, "unknown dialect");
127 Py_INCREF(dialect_obj);
128 return dialect_obj;
129}
130
131static int
132check_delattr(PyObject *v)
133{
134 if (v == NULL) {
135 PyErr_SetString(PyExc_TypeError,
136 "Cannot delete attribute");
137 return -1;
138 }
139 return 0;
140}
141
142static PyObject *
143get_string(PyObject *str)
144{
145 Py_XINCREF(str);
146 return str;
147}
148
149static int
150set_string(PyObject **str, PyObject *v)
151{
152 if (check_delattr(v) < 0)
153 return -1;
Skip Montanaro860fc0b2003-04-12 18:57:52 +0000154 if (!PyString_Check(v)
155#ifdef Py_USING_UNICODE
156&& !PyUnicode_Check(v)
157#endif
158) {
Skip Montanarob4a04172003-03-20 23:29:12 +0000159 PyErr_BadArgument();
160 return -1;
161 }
162 Py_XDECREF(*str);
163 Py_INCREF(v);
164 *str = v;
165 return 0;
166}
167
168static PyObject *
169get_nullchar_as_None(char c)
170{
171 if (c == '\0') {
172 Py_INCREF(Py_None);
173 return Py_None;
174 }
175 else
176 return PyString_FromStringAndSize((char*)&c, 1);
177}
178
179static int
180set_None_as_nullchar(char * addr, PyObject *v)
181{
182 if (check_delattr(v) < 0)
183 return -1;
184 if (v == Py_None)
185 *addr = '\0';
186 else if (!PyString_Check(v) || PyString_Size(v) != 1) {
187 PyErr_BadArgument();
188 return -1;
189 }
190 else
191 *addr = PyString_AsString(v)[0];
192 return 0;
193}
194
195static PyObject *
196Dialect_get_lineterminator(DialectObj *self)
197{
198 return get_string(self->lineterminator);
199}
200
201static int
202Dialect_set_lineterminator(DialectObj *self, PyObject *value)
203{
204 return set_string(&self->lineterminator, value);
205}
206
207static PyObject *
208Dialect_get_escapechar(DialectObj *self)
209{
210 return get_nullchar_as_None(self->escapechar);
211}
212
213static int
214Dialect_set_escapechar(DialectObj *self, PyObject *value)
215{
216 return set_None_as_nullchar(&self->escapechar, value);
217}
218
219static PyObject *
220Dialect_get_quoting(DialectObj *self)
221{
222 return PyInt_FromLong(self->quoting);
223}
224
225static int
226Dialect_set_quoting(DialectObj *self, PyObject *v)
227{
228 int quoting;
229 StyleDesc *qs = quote_styles;
230
231 if (check_delattr(v) < 0)
232 return -1;
233 if (!PyInt_Check(v)) {
234 PyErr_BadArgument();
235 return -1;
236 }
237 quoting = PyInt_AsLong(v);
238 for (qs = quote_styles; qs->name; qs++) {
239 if (qs->style == quoting) {
240 self->quoting = quoting;
241 return 0;
242 }
243 }
244 PyErr_BadArgument();
245 return -1;
246}
247
248static struct PyMethodDef Dialect_methods[] = {
249 { NULL, NULL }
250};
251
252#define D_OFF(x) offsetof(DialectObj, x)
253
254static struct PyMemberDef Dialect_memberlist[] = {
255 { "quotechar", T_CHAR, D_OFF(quotechar) },
256 { "delimiter", T_CHAR, D_OFF(delimiter) },
257 { "skipinitialspace", T_INT, D_OFF(skipinitialspace) },
258 { "doublequote", T_INT, D_OFF(doublequote) },
259 { "strict", T_INT, D_OFF(strict) },
260 { NULL }
261};
262
263static PyGetSetDef Dialect_getsetlist[] = {
264 { "escapechar", (getter)Dialect_get_escapechar,
265 (setter)Dialect_set_escapechar },
266 { "lineterminator", (getter)Dialect_get_lineterminator,
267 (setter)Dialect_set_lineterminator },
268 { "quoting", (getter)Dialect_get_quoting,
269 (setter)Dialect_set_quoting },
270 {NULL},
271};
272
273static void
274Dialect_dealloc(DialectObj *self)
275{
276 Py_XDECREF(self->lineterminator);
Skip Montanarob4a04172003-03-20 23:29:12 +0000277 self->ob_type->tp_free((PyObject *)self);
278}
279
280static int
281dialect_init(DialectObj * self, PyObject * args, PyObject * kwargs)
282{
283 PyObject *dialect = NULL, *name_obj, *value_obj;
284
285 self->quotechar = '"';
286 self->delimiter = ',';
287 self->escapechar = '\0';
288 self->skipinitialspace = 0;
289 Py_XDECREF(self->lineterminator);
290 self->lineterminator = PyString_FromString("\r\n");
291 if (self->lineterminator == NULL)
292 return -1;
293 self->quoting = QUOTE_MINIMAL;
294 self->doublequote = 1;
295 self->strict = 0;
296
297 if (!PyArg_ParseTuple(args, "|O", &dialect))
298 return -1;
299 Py_XINCREF(dialect);
300 if (kwargs != NULL) {
301 PyObject * key = PyString_FromString("dialect");
302 PyObject * d;
303
304 d = PyDict_GetItem(kwargs, key);
305 if (d) {
306 Py_INCREF(d);
307 Py_XDECREF(dialect);
308 PyDict_DelItem(kwargs, key);
309 dialect = d;
310 }
311 Py_DECREF(key);
312 }
313 if (dialect != NULL) {
314 int i;
315 PyObject * dir_list;
316
317 /* If dialect is a string, look it up in our registry */
Skip Montanaro860fc0b2003-04-12 18:57:52 +0000318 if (PyString_Check(dialect)
319#ifdef Py_USING_UNICODE
320|| PyUnicode_Check(dialect)
321#endif
322) {
Skip Montanarob4a04172003-03-20 23:29:12 +0000323 PyObject * new_dia;
324 new_dia = get_dialect_from_registry(dialect);
325 Py_DECREF(dialect);
326 if (new_dia == NULL)
327 return -1;
328 dialect = new_dia;
329 }
330 /* A class rather than an instance? Instanciate */
331 if (PyObject_TypeCheck(dialect, &PyClass_Type)) {
332 PyObject * new_dia;
333 new_dia = PyObject_CallFunction(dialect, "");
334 Py_DECREF(dialect);
335 if (new_dia == NULL)
336 return -1;
337 dialect = new_dia;
338 }
339 /* Make sure we finally have an instance */
340 if (!PyInstance_Check(dialect) ||
341 (dir_list = PyObject_Dir(dialect)) == NULL) {
342 PyErr_SetString(PyExc_TypeError,
343 "dialect must be an instance");
344 Py_DECREF(dialect);
345 return -1;
346 }
347 /* And extract the attributes */
348 for (i = 0; i < PyList_GET_SIZE(dir_list); ++i) {
349 name_obj = PyList_GET_ITEM(dir_list, i);
350 if (PyString_AsString(name_obj)[0] == '_')
351 continue;
352 value_obj = PyObject_GetAttr(dialect, name_obj);
353 if (value_obj) {
354 if (PyObject_SetAttr((PyObject *)self,
355 name_obj, value_obj)) {
356 Py_DECREF(dir_list);
357 return -1;
358 }
359 Py_DECREF(value_obj);
360 }
361 }
362 Py_DECREF(dir_list);
363 Py_DECREF(dialect);
364 }
365 if (kwargs != NULL) {
366 int pos = 0;
367
368 while (PyDict_Next(kwargs, &pos, &name_obj, &value_obj)) {
369 if (PyObject_SetAttr((PyObject *)self,
370 name_obj, value_obj))
371 return -1;
372 }
373 }
374 return 0;
375}
376
377static PyObject *
378dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
379{
380 DialectObj *self;
381 self = (DialectObj *)type->tp_alloc(type, 0);
382 if (self != NULL) {
383 self->lineterminator = NULL;
384 }
385 return (PyObject *)self;
386}
387
388
389PyDoc_STRVAR(Dialect_Type_doc,
390"CSV dialect\n"
391"\n"
392"The Dialect type records CSV parsing and generation options.\n");
393
394static PyTypeObject Dialect_Type = {
395 PyObject_HEAD_INIT(NULL)
396 0, /* ob_size */
397 "_csv.Dialect", /* tp_name */
398 sizeof(DialectObj), /* tp_basicsize */
399 0, /* tp_itemsize */
400 /* methods */
401 (destructor)Dialect_dealloc, /* tp_dealloc */
402 (printfunc)0, /* tp_print */
403 (getattrfunc)0, /* tp_getattr */
404 (setattrfunc)0, /* tp_setattr */
405 (cmpfunc)0, /* tp_compare */
406 (reprfunc)0, /* tp_repr */
407 0, /* tp_as_number */
408 0, /* tp_as_sequence */
409 0, /* tp_as_mapping */
410 (hashfunc)0, /* tp_hash */
411 (ternaryfunc)0, /* tp_call */
412 (reprfunc)0, /* tp_str */
413 0, /* tp_getattro */
414 0, /* tp_setattro */
415 0, /* tp_as_buffer */
416 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
417 Dialect_Type_doc, /* tp_doc */
418 0, /* tp_traverse */
419 0, /* tp_clear */
420 0, /* tp_richcompare */
421 0, /* tp_weaklistoffset */
422 0, /* tp_iter */
423 0, /* tp_iternext */
424 Dialect_methods, /* tp_methods */
425 Dialect_memberlist, /* tp_members */
426 Dialect_getsetlist, /* tp_getset */
427 0, /* tp_base */
428 0, /* tp_dict */
429 0, /* tp_descr_get */
430 0, /* tp_descr_set */
431 0, /* tp_dictoffset */
432 (initproc)dialect_init, /* tp_init */
433 PyType_GenericAlloc, /* tp_alloc */
434 dialect_new, /* tp_new */
435 0, /* tp_free */
436};
437
438static void
439parse_save_field(ReaderObj *self)
440{
441 PyObject *field;
442
443 field = PyString_FromStringAndSize(self->field, self->field_len);
444 if (field != NULL) {
445 PyList_Append(self->fields, field);
446 Py_XDECREF(field);
447 }
448 self->field_len = 0;
449}
450
451static int
452parse_grow_buff(ReaderObj *self)
453{
454 if (self->field_size == 0) {
455 self->field_size = 4096;
456 self->field = PyMem_Malloc(self->field_size);
457 }
458 else {
459 self->field_size *= 2;
460 self->field = PyMem_Realloc(self->field, self->field_size);
461 }
462 if (self->field == NULL) {
463 PyErr_NoMemory();
464 return 0;
465 }
466 return 1;
467}
468
469static void
470parse_add_char(ReaderObj *self, char c)
471{
472 if (self->field_len == self->field_size && !parse_grow_buff(self))
473 return;
474 self->field[self->field_len++] = c;
475}
476
477static void
478parse_process_char(ReaderObj *self, char c)
479{
480 DialectObj *dialect = self->dialect;
481
482 switch (self->state) {
483 case START_RECORD:
484 /* start of record */
485 if (c == '\n')
486 /* empty line - return [] */
487 break;
488 /* normal character - handle as START_FIELD */
489 self->state = START_FIELD;
490 /* fallthru */
491 case START_FIELD:
492 /* expecting field */
493 if (c == '\n') {
494 /* save empty field - return [fields] */
495 parse_save_field(self);
496 self->state = START_RECORD;
497 }
498 else if (c == dialect->quotechar) {
499 /* start quoted field */
500 self->state = IN_QUOTED_FIELD;
501 }
502 else if (c == dialect->escapechar) {
503 /* possible escaped character */
504 self->state = ESCAPED_CHAR;
505 }
506 else if (c == ' ' && dialect->skipinitialspace)
507 /* ignore space at start of field */
508 ;
509 else if (c == dialect->delimiter) {
510 /* save empty field */
511 parse_save_field(self);
512 }
513 else {
514 /* begin new unquoted field */
515 parse_add_char(self, c);
516 self->state = IN_FIELD;
517 }
518 break;
519
520 case ESCAPED_CHAR:
521 if (c != dialect->escapechar &&
522 c != dialect->delimiter &&
523 c != dialect->quotechar)
524 parse_add_char(self, dialect->escapechar);
525 parse_add_char(self, c);
526 self->state = IN_FIELD;
527 break;
528
529 case IN_FIELD:
530 /* in unquoted field */
531 if (c == '\n') {
532 /* end of line - return [fields] */
533 parse_save_field(self);
534 self->state = START_RECORD;
535 }
536 else if (c == dialect->escapechar) {
537 /* possible escaped character */
538 self->state = ESCAPED_CHAR;
539 }
540 else if (c == dialect->delimiter) {
541 /* save field - wait for new field */
542 parse_save_field(self);
543 self->state = START_FIELD;
544 }
545 else {
546 /* normal character - save in field */
547 parse_add_char(self, c);
548 }
549 break;
550
551 case IN_QUOTED_FIELD:
552 /* in quoted field */
553 if (c == '\n') {
554 /* end of line - save '\n' in field */
555 parse_add_char(self, '\n');
556 }
557 else if (c == dialect->escapechar) {
558 /* Possible escape character */
559 self->state = ESCAPE_IN_QUOTED_FIELD;
560 }
561 else if (c == dialect->quotechar) {
562 if (dialect->doublequote) {
563 /* doublequote; " represented by "" */
564 self->state = QUOTE_IN_QUOTED_FIELD;
565 }
566 else {
567 /* end of quote part of field */
568 self->state = IN_FIELD;
569 }
570 }
571 else {
572 /* normal character - save in field */
573 parse_add_char(self, c);
574 }
575 break;
576
577 case ESCAPE_IN_QUOTED_FIELD:
578 if (c != dialect->escapechar &&
579 c != dialect->delimiter &&
580 c != dialect->quotechar)
581 parse_add_char(self, dialect->escapechar);
582 parse_add_char(self, c);
583 self->state = IN_QUOTED_FIELD;
584 break;
585
586 case QUOTE_IN_QUOTED_FIELD:
587 /* doublequote - seen a quote in an quoted field */
588 if (dialect->quoting != QUOTE_NONE &&
589 c == dialect->quotechar) {
590 /* save "" as " */
591 parse_add_char(self, c);
592 self->state = IN_QUOTED_FIELD;
593 }
594 else if (c == dialect->delimiter) {
595 /* save field - wait for new field */
596 parse_save_field(self);
597 self->state = START_FIELD;
598 }
599 else if (c == '\n') {
600 /* end of line - return [fields] */
601 parse_save_field(self);
602 self->state = START_RECORD;
603 }
604 else if (!dialect->strict) {
605 parse_add_char(self, c);
606 self->state = IN_FIELD;
607 }
608 else {
609 /* illegal */
610 self->had_parse_error = 1;
611 PyErr_Format(error_obj, "%c expected after %c",
612 dialect->delimiter,
613 dialect->quotechar);
614 }
615 break;
616
617 }
618}
619
620/*
621 * READER
622 */
623#define R_OFF(x) offsetof(ReaderObj, x)
624
625static struct PyMemberDef Reader_memberlist[] = {
626 { "dialect", T_OBJECT, R_OFF(dialect), RO },
627 { NULL }
628};
629
630static PyObject *
631Reader_getiter(ReaderObj *self)
632{
633 Py_INCREF(self);
634 return (PyObject *)self;
635}
636
637static PyObject *
638Reader_iternext(ReaderObj *self)
639{
640 PyObject *lineobj;
641 PyObject *fields;
642 char *line;
643
644 do {
645 lineobj = PyIter_Next(self->input_iter);
646 if (lineobj == NULL) {
647 /* End of input OR exception */
648 if (!PyErr_Occurred() && self->field_len != 0)
649 return PyErr_Format(error_obj,
650 "newline inside string");
651 return NULL;
652 }
653
654 if (self->had_parse_error) {
655 if (self->fields) {
656 Py_XDECREF(self->fields);
657 }
658 self->fields = PyList_New(0);
659 self->field_len = 0;
660 self->state = START_RECORD;
661 self->had_parse_error = 0;
662 }
663 line = PyString_AsString(lineobj);
664
665 if (line == NULL) {
666 Py_DECREF(lineobj);
667 return NULL;
668 }
Tim Petersef4b7ed2003-03-21 01:35:28 +0000669 if (strlen(line) < (size_t)PyString_GET_SIZE(lineobj)) {
Skip Montanarob4a04172003-03-20 23:29:12 +0000670 self->had_parse_error = 1;
671 Py_DECREF(lineobj);
672 return PyErr_Format(error_obj,
673 "string with NUL bytes");
674 }
675
676 /* Process line of text - send '\n' to processing code to
677 represent end of line. End of line which is not at end of
678 string is an error. */
679 while (*line) {
680 char c;
681
682 c = *line++;
683 if (c == '\r') {
684 c = *line++;
685 if (c == '\0')
686 /* macintosh end of line */
687 break;
688 if (c == '\n') {
689 c = *line++;
690 if (c == '\0')
691 /* DOS end of line */
692 break;
693 }
694 self->had_parse_error = 1;
695 Py_DECREF(lineobj);
696 return PyErr_Format(error_obj,
697 "newline inside string");
698 }
699 if (c == '\n') {
700 c = *line++;
701 if (c == '\0')
702 /* unix end of line */
703 break;
704 self->had_parse_error = 1;
705 Py_DECREF(lineobj);
706 return PyErr_Format(error_obj,
707 "newline inside string");
708 }
709 parse_process_char(self, c);
710 if (PyErr_Occurred()) {
711 Py_DECREF(lineobj);
712 return NULL;
713 }
714 }
715 parse_process_char(self, '\n');
716 Py_DECREF(lineobj);
717 } while (self->state != START_RECORD);
718
719 fields = self->fields;
720 self->fields = PyList_New(0);
721 return fields;
722}
723
724static void
725Reader_dealloc(ReaderObj *self)
726{
727 Py_XDECREF(self->dialect);
728 Py_XDECREF(self->input_iter);
729 Py_XDECREF(self->fields);
730 PyMem_DEL(self);
731}
732
733PyDoc_STRVAR(Reader_Type_doc,
734"CSV reader\n"
735"\n"
736"Reader objects are responsible for reading and parsing tabular data\n"
737"in CSV format.\n"
738);
739
740static struct PyMethodDef Reader_methods[] = {
741 { NULL, NULL }
742};
743
744static PyTypeObject Reader_Type = {
745 PyObject_HEAD_INIT(NULL)
746 0, /*ob_size*/
747 "_csv.reader", /*tp_name*/
748 sizeof(ReaderObj), /*tp_basicsize*/
749 0, /*tp_itemsize*/
750 /* methods */
751 (destructor)Reader_dealloc, /*tp_dealloc*/
752 (printfunc)0, /*tp_print*/
753 (getattrfunc)0, /*tp_getattr*/
754 (setattrfunc)0, /*tp_setattr*/
755 (cmpfunc)0, /*tp_compare*/
756 (reprfunc)0, /*tp_repr*/
757 0, /*tp_as_number*/
758 0, /*tp_as_sequence*/
759 0, /*tp_as_mapping*/
760 (hashfunc)0, /*tp_hash*/
761 (ternaryfunc)0, /*tp_call*/
762 (reprfunc)0, /*tp_str*/
763 0, /*tp_getattro*/
764 0, /*tp_setattro*/
765 0, /*tp_as_buffer*/
766 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
767 Reader_Type_doc, /*tp_doc*/
768 0, /*tp_traverse*/
769 0, /*tp_clear*/
770 0, /*tp_richcompare*/
771 0, /*tp_weaklistoffset*/
772 (getiterfunc)Reader_getiter, /*tp_iter*/
773 (getiterfunc)Reader_iternext, /*tp_iternext*/
774 Reader_methods, /*tp_methods*/
775 Reader_memberlist, /*tp_members*/
776 0, /*tp_getset*/
777
778};
779
780static PyObject *
781csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args)
782{
783 PyObject * iterator, * dialect = NULL, *ctor_args;
784 ReaderObj * self = PyObject_NEW(ReaderObj, &Reader_Type);
785
786 if (!self)
787 return NULL;
788
789 self->dialect = NULL;
790 self->input_iter = self->fields = NULL;
791
792 self->fields = NULL;
793 self->input_iter = NULL;
794 self->had_parse_error = 0;
795 self->field = NULL;
796 self->field_size = 0;
797 self->field_len = 0;
798 self->state = START_RECORD;
799
800 if (!PyArg_ParseTuple(args, "O|O", &iterator, &dialect)) {
801 Py_DECREF(self);
802 return NULL;
803 }
804 self->input_iter = PyObject_GetIter(iterator);
805 if (self->input_iter == NULL) {
806 PyErr_SetString(PyExc_TypeError,
807 "argument 1 must be an iterator");
808 Py_DECREF(self);
809 return NULL;
810 }
811 ctor_args = Py_BuildValue(dialect ? "(O)" : "()", dialect);
812 if (ctor_args == NULL) {
813 Py_DECREF(self);
814 return NULL;
815 }
816 self->dialect = (DialectObj *)PyObject_Call((PyObject *)&Dialect_Type,
817 ctor_args, keyword_args);
818 Py_DECREF(ctor_args);
819 if (self->dialect == NULL) {
820 Py_DECREF(self);
821 return NULL;
822 }
823 self->fields = PyList_New(0);
824 if (self->fields == NULL) {
825 Py_DECREF(self);
826 return NULL;
827 }
828
829 return (PyObject *)self;
830}
831
832/*
833 * WRITER
834 */
835/* ---------------------------------------------------------------- */
836static void
837join_reset(WriterObj *self)
838{
839 self->rec_len = 0;
840 self->num_fields = 0;
841}
842
843#define MEM_INCR 32768
844
845/* Calculate new record length or append field to record. Return new
846 * record length.
847 */
848static int
849join_append_data(WriterObj *self, char *field, int quote_empty,
850 int *quoted, int copy_phase)
851{
852 DialectObj *dialect = self->dialect;
853 int i, rec_len;
854
855 rec_len = self->rec_len;
856
857 /* If this is not the first field we need a field separator.
858 */
859 if (self->num_fields > 0) {
860 if (copy_phase)
861 self->rec[rec_len] = dialect->delimiter;
862 rec_len++;
863 }
864 /* Handle preceding quote.
865 */
866 switch (dialect->quoting) {
867 case QUOTE_ALL:
868 *quoted = 1;
869 if (copy_phase)
870 self->rec[rec_len] = dialect->quotechar;
871 rec_len++;
872 break;
873 case QUOTE_MINIMAL:
874 case QUOTE_NONNUMERIC:
875 /* We only know about quoted in the copy phase.
876 */
877 if (copy_phase && *quoted) {
878 self->rec[rec_len] = dialect->quotechar;
879 rec_len++;
880 }
881 break;
882 case QUOTE_NONE:
883 break;
884 }
885 /* Copy/count field data.
886 */
887 for (i = 0;; i++) {
888 char c = field[i];
889
890 if (c == '\0')
891 break;
892 /* If in doublequote mode we escape quote chars with a
893 * quote.
894 */
895 if (dialect->quoting != QUOTE_NONE &&
896 c == dialect->quotechar && dialect->doublequote) {
897 if (copy_phase)
898 self->rec[rec_len] = dialect->quotechar;
899 *quoted = 1;
900 rec_len++;
901 }
902
903 /* Some special characters need to be escaped. If we have a
904 * quote character switch to quoted field instead of escaping
905 * individual characters.
906 */
907 if (!*quoted
908 && (c == dialect->delimiter ||
909 c == dialect->escapechar ||
910 c == '\n' || c == '\r')) {
911 if (dialect->quoting != QUOTE_NONE)
912 *quoted = 1;
913 else if (dialect->escapechar) {
914 if (copy_phase)
915 self->rec[rec_len] = dialect->escapechar;
916 rec_len++;
917 }
918 else {
919 PyErr_Format(error_obj,
920 "delimiter must be quoted or escaped");
921 return -1;
922 }
923 }
924 /* Copy field character into record buffer.
925 */
926 if (copy_phase)
927 self->rec[rec_len] = c;
928 rec_len++;
929 }
930
931 /* If field is empty check if it needs to be quoted.
932 */
933 if (i == 0 && quote_empty) {
934 if (dialect->quoting == QUOTE_NONE) {
935 PyErr_Format(error_obj,
936 "single empty field record must be quoted");
937 return -1;
938 } else
939 *quoted = 1;
940 }
941
942 /* Handle final quote character on field.
943 */
944 if (*quoted) {
945 if (copy_phase)
946 self->rec[rec_len] = dialect->quotechar;
947 else
948 /* Didn't know about leading quote until we found it
949 * necessary in field data - compensate for it now.
950 */
951 rec_len++;
952 rec_len++;
953 }
954
955 return rec_len;
956}
957
958static int
959join_check_rec_size(WriterObj *self, int rec_len)
960{
961 if (rec_len > self->rec_size) {
962 if (self->rec_size == 0) {
963 self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
964 self->rec = PyMem_Malloc(self->rec_size);
965 }
966 else {
967 char *old_rec = self->rec;
968
969 self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
970 self->rec = PyMem_Realloc(self->rec, self->rec_size);
971 if (self->rec == NULL)
972 PyMem_Free(old_rec);
973 }
974 if (self->rec == NULL) {
975 PyErr_NoMemory();
976 return 0;
977 }
978 }
979 return 1;
980}
981
982static int
983join_append(WriterObj *self, char *field, int *quoted, int quote_empty)
984{
985 int rec_len;
986
987 rec_len = join_append_data(self, field, quote_empty, quoted, 0);
988 if (rec_len < 0)
989 return 0;
990
991 /* grow record buffer if necessary */
992 if (!join_check_rec_size(self, rec_len))
993 return 0;
994
995 self->rec_len = join_append_data(self, field, quote_empty, quoted, 1);
996 self->num_fields++;
997
998 return 1;
999}
1000
1001static int
1002join_append_lineterminator(WriterObj *self)
1003{
1004 int terminator_len;
1005
1006 terminator_len = PyString_Size(self->dialect->lineterminator);
1007
1008 /* grow record buffer if necessary */
1009 if (!join_check_rec_size(self, self->rec_len + terminator_len))
1010 return 0;
1011
1012 memmove(self->rec + self->rec_len,
1013 PyString_AsString(self->dialect->lineterminator),
1014 terminator_len);
1015 self->rec_len += terminator_len;
1016
1017 return 1;
1018}
1019
1020PyDoc_STRVAR(csv_writerow_doc,
Skip Montanaro860fc0b2003-04-12 18:57:52 +00001021"writerow(sequence)\n"
Skip Montanarob4a04172003-03-20 23:29:12 +00001022"\n"
Skip Montanaro860fc0b2003-04-12 18:57:52 +00001023"Construct and write a CSV record from a sequence of fields. Non-string\n"
Skip Montanarob4a04172003-03-20 23:29:12 +00001024"elements will be converted to string.");
1025
1026static PyObject *
1027csv_writerow(WriterObj *self, PyObject *seq)
1028{
1029 DialectObj *dialect = self->dialect;
1030 int len, i;
1031
1032 if (!PySequence_Check(seq))
1033 return PyErr_Format(error_obj, "sequence expected");
1034
1035 len = PySequence_Length(seq);
1036 if (len < 0)
1037 return NULL;
1038
1039 /* Join all fields in internal buffer.
1040 */
1041 join_reset(self);
1042 for (i = 0; i < len; i++) {
1043 PyObject *field;
1044 int append_ok;
1045 int quoted;
1046
1047 field = PySequence_GetItem(seq, i);
1048 if (field == NULL)
1049 return NULL;
1050
1051 quoted = 0;
1052 if (dialect->quoting == QUOTE_NONNUMERIC) {
1053 PyObject *num;
1054
1055 num = PyNumber_Float(field);
1056 if (num == NULL) {
1057 quoted = 1;
1058 PyErr_Clear();
1059 }
1060 else {
1061 Py_DECREF(num);
1062 }
1063 }
1064
1065 if (PyString_Check(field)) {
1066 append_ok = join_append(self, PyString_AsString(field),
1067 &quoted, len == 1);
1068 Py_DECREF(field);
1069 }
1070 else if (field == Py_None) {
1071 append_ok = join_append(self, "", &quoted, len == 1);
1072 Py_DECREF(field);
1073 }
1074 else {
1075 PyObject *str;
1076
1077 str = PyObject_Str(field);
1078 Py_DECREF(field);
1079 if (str == NULL)
1080 return NULL;
1081
1082 append_ok = join_append(self, PyString_AsString(str),
1083 &quoted, len == 1);
1084 Py_DECREF(str);
1085 }
1086 if (!append_ok)
1087 return NULL;
1088 }
1089
1090 /* Add line terminator.
1091 */
1092 if (!join_append_lineterminator(self))
1093 return 0;
1094
1095 return PyObject_CallFunction(self->writeline,
1096 "(s#)", self->rec, self->rec_len);
1097}
1098
Skip Montanaro860fc0b2003-04-12 18:57:52 +00001099PyDoc_STRVAR(csv_writerows_doc,
1100"writerows(sequence of sequences)\n"
1101"\n"
1102"Construct and write a series of sequences to a csv file. Non-string\n"
1103"elements will be converted to string.");
1104
Skip Montanarob4a04172003-03-20 23:29:12 +00001105static PyObject *
1106csv_writerows(WriterObj *self, PyObject *seqseq)
1107{
1108 PyObject *row_iter, *row_obj, *result;
1109
1110 row_iter = PyObject_GetIter(seqseq);
1111 if (row_iter == NULL) {
1112 PyErr_SetString(PyExc_TypeError,
Skip Montanaro98f16e02003-04-11 23:10:13 +00001113 "writerows() argument must be iterable");
Skip Montanarob4a04172003-03-20 23:29:12 +00001114 return NULL;
1115 }
1116 while ((row_obj = PyIter_Next(row_iter))) {
1117 result = csv_writerow(self, row_obj);
1118 Py_DECREF(row_obj);
1119 if (!result) {
1120 Py_DECREF(row_iter);
1121 return NULL;
1122 }
1123 else
1124 Py_DECREF(result);
1125 }
1126 Py_DECREF(row_iter);
1127 if (PyErr_Occurred())
1128 return NULL;
1129 Py_INCREF(Py_None);
1130 return Py_None;
1131}
1132
1133static struct PyMethodDef Writer_methods[] = {
1134 { "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc},
Skip Montanaro860fc0b2003-04-12 18:57:52 +00001135 { "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc},
Skip Montanarob4a04172003-03-20 23:29:12 +00001136 { NULL, NULL }
1137};
1138
1139#define W_OFF(x) offsetof(WriterObj, x)
1140
1141static struct PyMemberDef Writer_memberlist[] = {
1142 { "dialect", T_OBJECT, W_OFF(dialect), RO },
1143 { NULL }
1144};
1145
1146static void
1147Writer_dealloc(WriterObj *self)
1148{
1149 Py_XDECREF(self->dialect);
1150 Py_XDECREF(self->writeline);
1151 PyMem_DEL(self);
1152}
1153
1154PyDoc_STRVAR(Writer_Type_doc,
1155"CSV writer\n"
1156"\n"
1157"Writer objects are responsible for generating tabular data\n"
1158"in CSV format from sequence input.\n"
1159);
1160
1161static PyTypeObject Writer_Type = {
1162 PyObject_HEAD_INIT(NULL)
1163 0, /*ob_size*/
1164 "_csv.writer", /*tp_name*/
1165 sizeof(WriterObj), /*tp_basicsize*/
1166 0, /*tp_itemsize*/
1167 /* methods */
1168 (destructor)Writer_dealloc, /*tp_dealloc*/
1169 (printfunc)0, /*tp_print*/
1170 (getattrfunc)0, /*tp_getattr*/
1171 (setattrfunc)0, /*tp_setattr*/
1172 (cmpfunc)0, /*tp_compare*/
1173 (reprfunc)0, /*tp_repr*/
1174 0, /*tp_as_number*/
1175 0, /*tp_as_sequence*/
1176 0, /*tp_as_mapping*/
1177 (hashfunc)0, /*tp_hash*/
1178 (ternaryfunc)0, /*tp_call*/
1179 (reprfunc)0, /*tp_str*/
1180 0, /*tp_getattro*/
1181 0, /*tp_setattro*/
1182 0, /*tp_as_buffer*/
1183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1184 Writer_Type_doc,
1185 0, /*tp_traverse*/
1186 0, /*tp_clear*/
1187 0, /*tp_richcompare*/
1188 0, /*tp_weaklistoffset*/
1189 (getiterfunc)0, /*tp_iter*/
1190 (getiterfunc)0, /*tp_iternext*/
1191 Writer_methods, /*tp_methods*/
1192 Writer_memberlist, /*tp_members*/
1193 0, /*tp_getset*/
1194};
1195
1196static PyObject *
1197csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
1198{
1199 PyObject * output_file, * dialect = NULL, *ctor_args;
1200 WriterObj * self = PyObject_NEW(WriterObj, &Writer_Type);
1201
1202 if (!self)
1203 return NULL;
1204
1205 self->dialect = NULL;
1206 self->writeline = NULL;
1207
1208 self->rec = NULL;
1209 self->rec_size = 0;
1210 self->rec_len = 0;
1211 self->num_fields = 0;
1212
1213 if (!PyArg_ParseTuple(args, "O|O", &output_file, &dialect)) {
1214 Py_DECREF(self);
1215 return NULL;
1216 }
1217 self->writeline = PyObject_GetAttrString(output_file, "write");
1218 if (self->writeline == NULL || !PyCallable_Check(self->writeline)) {
1219 PyErr_SetString(PyExc_TypeError,
1220 "argument 1 must be an instance with a write method");
1221 Py_DECREF(self);
1222 return NULL;
1223 }
1224 ctor_args = Py_BuildValue(dialect ? "(O)" : "()", dialect);
1225 if (ctor_args == NULL) {
1226 Py_DECREF(self);
1227 return NULL;
1228 }
1229 self->dialect = (DialectObj *)PyObject_Call((PyObject *)&Dialect_Type,
1230 ctor_args, keyword_args);
1231 Py_DECREF(ctor_args);
1232 if (self->dialect == NULL) {
1233 Py_DECREF(self);
1234 return NULL;
1235 }
1236 return (PyObject *)self;
1237}
1238
1239/*
1240 * DIALECT REGISTRY
1241 */
1242static PyObject *
1243csv_list_dialects(PyObject *module, PyObject *args)
1244{
1245 return PyDict_Keys(dialects);
1246}
1247
1248static PyObject *
1249csv_register_dialect(PyObject *module, PyObject *args)
1250{
1251 PyObject *name_obj, *dialect_obj;
1252
1253 if (!PyArg_ParseTuple(args, "OO", &name_obj, &dialect_obj))
1254 return NULL;
Skip Montanaro860fc0b2003-04-12 18:57:52 +00001255 if (!PyString_Check(name_obj)
1256#ifdef Py_USING_UNICODE
1257&& !PyUnicode_Check(name_obj)
1258#endif
1259) {
Skip Montanarob4a04172003-03-20 23:29:12 +00001260 PyErr_SetString(PyExc_TypeError,
1261 "dialect name must be a string or unicode");
1262 return NULL;
1263 }
1264 Py_INCREF(dialect_obj);
1265 /* A class rather than an instance? Instanciate */
1266 if (PyObject_TypeCheck(dialect_obj, &PyClass_Type)) {
1267 PyObject * new_dia;
1268 new_dia = PyObject_CallFunction(dialect_obj, "");
1269 Py_DECREF(dialect_obj);
1270 if (new_dia == NULL)
1271 return NULL;
1272 dialect_obj = new_dia;
1273 }
1274 /* Make sure we finally have an instance */
1275 if (!PyInstance_Check(dialect_obj)) {
1276 PyErr_SetString(PyExc_TypeError, "dialect must be an instance");
1277 Py_DECREF(dialect_obj);
1278 return NULL;
1279 }
1280 if (PyObject_SetAttrString(dialect_obj, "_name", name_obj) < 0) {
1281 Py_DECREF(dialect_obj);
1282 return NULL;
1283 }
1284 if (PyDict_SetItem(dialects, name_obj, dialect_obj) < 0) {
1285 Py_DECREF(dialect_obj);
1286 return NULL;
1287 }
1288 Py_DECREF(dialect_obj);
1289 Py_INCREF(Py_None);
1290 return Py_None;
1291}
1292
1293static PyObject *
1294csv_unregister_dialect(PyObject *module, PyObject *args)
1295{
1296 PyObject *name_obj;
1297
1298 if (!PyArg_ParseTuple(args, "O", &name_obj))
1299 return NULL;
1300 if (PyDict_DelItem(dialects, name_obj) < 0)
1301 return PyErr_Format(error_obj, "unknown dialect");
1302 Py_INCREF(Py_None);
1303 return Py_None;
1304}
1305
1306static PyObject *
1307csv_get_dialect(PyObject *module, PyObject *args)
1308{
1309 PyObject *name_obj;
1310
1311 if (!PyArg_ParseTuple(args, "O", &name_obj))
1312 return NULL;
1313 return get_dialect_from_registry(name_obj);
1314}
1315
1316/*
1317 * MODULE
1318 */
1319
1320PyDoc_STRVAR(csv_module_doc,
1321"CSV parsing and writing.\n"
1322"\n"
1323"This module provides classes that assist in the reading and writing\n"
1324"of Comma Separated Value (CSV) files, and implements the interface\n"
1325"described by PEP 305. Although many CSV files are simple to parse,\n"
1326"the format is not formally defined by a stable specification and\n"
1327"is subtle enough that parsing lines of a CSV file with something\n"
1328"like line.split(\",\") is bound to fail. The module supports three\n"
1329"basic APIs: reading, writing, and registration of dialects.\n"
1330"\n"
1331"\n"
1332"DIALECT REGISTRATION:\n"
1333"\n"
1334"Readers and writers support a dialect argument, which is a convenient\n"
1335"handle on a group of settings. When the dialect argument is a string,\n"
1336"it identifies one of the dialects previously registered with the module.\n"
1337"If it is a class or instance, the attributes of the argument are used as\n"
1338"the settings for the reader or writer:\n"
1339"\n"
1340" class excel:\n"
1341" delimiter = ','\n"
1342" quotechar = '\"'\n"
1343" escapechar = None\n"
1344" doublequote = True\n"
1345" skipinitialspace = False\n"
1346" lineterminator = '\r\n'\n"
1347" quoting = QUOTE_MINIMAL\n"
1348"\n"
1349"SETTINGS:\n"
1350"\n"
1351" * quotechar - specifies a one-character string to use as the \n"
1352" quoting character. It defaults to '\"'.\n"
1353" * delimiter - specifies a one-character string to use as the \n"
1354" field separator. It defaults to ','.\n"
1355" * skipinitialspace - specifies how to interpret whitespace which\n"
1356" immediately follows a delimiter. It defaults to False, which\n"
1357" means that whitespace immediately following a delimiter is part\n"
1358" of the following field.\n"
1359" * lineterminator - specifies the character sequence which should \n"
1360" terminate rows.\n"
1361" * quoting - controls when quotes should be generated by the writer.\n"
1362" It can take on any of the following module constants:\n"
1363"\n"
1364" csv.QUOTE_MINIMAL means only when required, for example, when a\n"
1365" field contains either the quotechar or the delimiter\n"
1366" csv.QUOTE_ALL means that quotes are always placed around fields.\n"
1367" csv.QUOTE_NONNUMERIC means that quotes are always placed around\n"
1368" fields which contain characters other than [+-0-9.].\n"
1369" csv.QUOTE_NONE means that quotes are never placed around fields.\n"
1370" * escapechar - specifies a one-character string used to escape \n"
1371" the delimiter when quoting is set to QUOTE_NONE.\n"
1372" * doublequote - controls the handling of quotes inside fields. When\n"
1373" True, two consecutive quotes are interpreted as one during read,\n"
1374" and when writing, each quote character embedded in the data is\n"
1375" written as two quotes\n");
1376
1377PyDoc_STRVAR(csv_reader_doc,
1378" csv_reader = reader(iterable [, dialect='excel']\n"
1379" [optional keyword args])\n"
1380" for row in csv_reader:\n"
1381" process(row)\n"
1382"\n"
1383"The \"iterable\" argument can be any object that returns a line\n"
1384"of input for each iteration, such as a file object or a list. The\n"
1385"optional \"dialect\" parameter is discussed below. The function\n"
1386"also accepts optional keyword arguments which override settings\n"
1387"provided by the dialect.\n"
1388"\n"
1389"The returned object is an iterator. Each iteration returns a row\n"
1390 "of the CSV file (which can span multiple input lines):\n");
1391
1392PyDoc_STRVAR(csv_writer_doc,
1393" csv_writer = csv.writer(fileobj [, dialect='excel']\n"
1394" [optional keyword args])\n"
1395" for row in csv_writer:\n"
1396" csv_writer.writerow(row)\n"
1397"\n"
1398" [or]\n"
1399"\n"
1400" csv_writer = csv.writer(fileobj [, dialect='excel']\n"
1401" [optional keyword args])\n"
1402" csv_writer.writerows(rows)\n"
1403"\n"
1404"The \"fileobj\" argument can be any object that supports the file API.\n");
1405
1406PyDoc_STRVAR(csv_list_dialects_doc,
1407"Return a list of all know dialect names.\n"
1408" names = csv.list_dialects()");
1409
1410PyDoc_STRVAR(csv_get_dialect_doc,
1411"Return the dialect instance associated with name.\n"
1412" dialect = csv.get_dialect(name)");
1413
1414PyDoc_STRVAR(csv_register_dialect_doc,
1415"Create a mapping from a string name to a dialect class.\n"
1416" dialect = csv.register_dialect(name, dialect)");
1417
1418PyDoc_STRVAR(csv_unregister_dialect_doc,
1419"Delete the name/dialect mapping associated with a string name.\n"
1420" csv.unregister_dialect(name)");
1421
1422static struct PyMethodDef csv_methods[] = {
1423 { "reader", (PyCFunction)csv_reader,
1424 METH_VARARGS | METH_KEYWORDS, csv_reader_doc},
1425 { "writer", (PyCFunction)csv_writer,
1426 METH_VARARGS | METH_KEYWORDS, csv_writer_doc},
1427 { "list_dialects", (PyCFunction)csv_list_dialects,
1428 METH_NOARGS, csv_list_dialects_doc},
1429 { "register_dialect", (PyCFunction)csv_register_dialect,
1430 METH_VARARGS, csv_register_dialect_doc},
1431 { "unregister_dialect", (PyCFunction)csv_unregister_dialect,
1432 METH_VARARGS, csv_unregister_dialect_doc},
1433 { "get_dialect", (PyCFunction)csv_get_dialect,
1434 METH_VARARGS, csv_get_dialect_doc},
1435 { NULL, NULL }
1436};
1437
1438PyMODINIT_FUNC
1439init_csv(void)
1440{
1441 PyObject *module;
1442 PyObject *rev;
1443 PyObject *v;
1444 int res;
1445 StyleDesc *style;
1446
1447 if (PyType_Ready(&Dialect_Type) < 0)
1448 return;
1449
1450 if (PyType_Ready(&Reader_Type) < 0)
1451 return;
1452
1453 if (PyType_Ready(&Writer_Type) < 0)
1454 return;
1455
1456 /* Create the module and add the functions */
1457 module = Py_InitModule3("_csv", csv_methods, csv_module_doc);
1458 if (module == NULL)
1459 return;
1460
1461 /* Add version to the module. */
1462 rev = PyString_FromString("1.0");
1463 if (rev == NULL)
1464 return;
1465 if (PyModule_AddObject(module, "__version__", rev) < 0)
1466 return;
1467
1468 /* Add _dialects dictionary */
1469 dialects = PyDict_New();
1470 if (dialects == NULL)
1471 return;
1472 if (PyModule_AddObject(module, "_dialects", dialects))
1473 return;
1474
1475 /* Add quote styles into dictionary */
1476 for (style = quote_styles; style->name; style++) {
1477 v = PyInt_FromLong(style->style);
1478 if (v == NULL)
1479 return;
1480 res = PyModule_AddObject(module, style->name, v);
1481 if (res < 0)
1482 return;
1483 }
1484
1485 /* Add the Dialect type */
1486 if (PyModule_AddObject(module, "Dialect", (PyObject *)&Dialect_Type))
1487 return;
1488
1489 /* Add the CSV exception object to the module. */
1490 error_obj = PyErr_NewException("_csv.Error", NULL, NULL);
1491 if (error_obj == NULL)
1492 return;
1493 PyModule_AddObject(module, "Error", error_obj);
1494}