| 
									
										
										
										
											2003-03-23 14:32:54 +00:00
										 |  |  | /* csv module */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This module provides the low-level underpinnings of a CSV reading/writing | 
					
						
							|  |  |  | module.  Users should not use this module directly, but import the csv.py | 
					
						
							|  |  |  | module instead. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-12 19:23:46 +00:00
										 |  |  | #define MODULE_VERSION "1.0"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-10 12:22:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject *error_obj;   /* CSV exception */ | 
					
						
							|  |  |  |     PyObject *dialects;   /* Dialect registry */ | 
					
						
							|  |  |  |     long field_limit;   /* max parsed field size */ | 
					
						
							|  |  |  | } _csvstate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define _csvstate(o) ((_csvstate *)PyModule_GetState(o))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _csv_clear(PyObject *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_CLEAR(_csvstate(m)->error_obj); | 
					
						
							|  |  |  |     Py_CLEAR(_csvstate(m)->dialects); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _csv_traverse(PyObject *m, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_VISIT(_csvstate(m)->error_obj); | 
					
						
							|  |  |  |     Py_VISIT(_csvstate(m)->dialects); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | _csv_free(void *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    _csv_clear((PyObject *)m); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _csvmodule; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define _csvstate_global ((_csvstate *)PyModule_GetState(PyState_FindModule(&_csvmodule)))
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef enum { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, | 
					
						
							|  |  |  |     IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD, | 
					
						
							| 
									
										
										
										
											2013-03-19 22:41:47 -04:00
										 |  |  |     EAT_CRNL,AFTER_ESCAPED_CRNL | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } ParserState; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef enum { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } QuoteStyle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     QuoteStyle style; | 
					
						
							|  |  |  |     char *name; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } StyleDesc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static StyleDesc quote_styles[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { QUOTE_MINIMAL,    "QUOTE_MINIMAL" }, | 
					
						
							|  |  |  |     { QUOTE_ALL,        "QUOTE_ALL" }, | 
					
						
							|  |  |  |     { QUOTE_NONNUMERIC, "QUOTE_NONNUMERIC" }, | 
					
						
							|  |  |  |     { QUOTE_NONE,       "QUOTE_NONE" }, | 
					
						
							|  |  |  |     { 0 } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							| 
									
										
										
										
											2007-08-06 19:32:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int doublequote;            /* is " represented by ""? */ | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     Py_UCS4 delimiter;       /* field separator */ | 
					
						
							|  |  |  |     Py_UCS4 quotechar;       /* quote character */ | 
					
						
							|  |  |  |     Py_UCS4 escapechar;      /* escape character */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int skipinitialspace;       /* ignore spaces following delimiter? */ | 
					
						
							|  |  |  |     PyObject *lineterminator; /* string to write between records */ | 
					
						
							|  |  |  |     int quoting;                /* style of quoting to write */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int strict;                 /* raise exception on bad CSV */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } DialectObj; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-22 09:28:35 +00:00
										 |  |  | static PyTypeObject Dialect_Type; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *input_iter;   /* iterate over this for input lines */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *dialect;    /* parsing dialect */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *fields;           /* field list for current record */ | 
					
						
							|  |  |  |     ParserState state;          /* current CSV parse state */ | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     Py_UCS4 *field;             /* temporary buffer */ | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     Py_ssize_t field_size;      /* size of allocated buffer */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_ssize_t field_len;       /* length of current field */ | 
					
						
							|  |  |  |     int numeric_field;          /* treat field as numeric */ | 
					
						
							|  |  |  |     unsigned long line_num;     /* Source-file line number */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } ReaderObj; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-22 09:28:35 +00:00
										 |  |  | static PyTypeObject Reader_Type; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-19 02:45:37 +00:00
										 |  |  | #define ReaderObject_Check(v)   (Py_TYPE(v) == &Reader_Type)
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *writeline;    /* write output lines to this file */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *dialect;    /* parsing dialect */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     Py_UCS4 *rec;            /* buffer for parser.join */ | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     Py_ssize_t rec_size;        /* size of allocated record */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_ssize_t rec_len;         /* length of record */ | 
					
						
							|  |  |  |     int num_fields;             /* number of fields in record */ | 
					
						
							| 
									
										
										
										
											2007-08-06 19:32:18 +00:00
										 |  |  | } WriterObj; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-22 09:28:35 +00:00
										 |  |  | static PyTypeObject Writer_Type; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * DIALECT class | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | get_dialect_from_registry(PyObject * name_obj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *dialect_obj; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     dialect_obj = PyDict_GetItem(_csvstate_global->dialects, name_obj); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (dialect_obj == NULL) { | 
					
						
							|  |  |  |         if (!PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |             PyErr_Format(_csvstate_global->error_obj, "unknown dialect"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         Py_INCREF(dialect_obj); | 
					
						
							|  |  |  |     return dialect_obj; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | get_string(PyObject *str) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_XINCREF(str); | 
					
						
							|  |  |  |     return str; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | get_nullchar_as_None(Py_UCS4 c) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (c == '\0') { | 
					
						
							|  |  |  |         Py_INCREF(Py_None); | 
					
						
							|  |  |  |         return Py_None; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |         return PyUnicode_FromOrdinal(c); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | Dialect_get_lineterminator(DialectObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return get_string(self->lineterminator); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-07 23:59:30 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | Dialect_get_delimiter(DialectObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return get_nullchar_as_None(self->delimiter); | 
					
						
							| 
									
										
										
										
											2007-08-07 23:59:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | Dialect_get_escapechar(DialectObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return get_nullchar_as_None(self->escapechar); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | Dialect_get_quotechar(DialectObj *self) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return get_nullchar_as_None(self->quotechar); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | Dialect_get_quoting(DialectObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return PyLong_FromLong(self->quoting); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | _set_bool(const char *name, int *target, PyObject *src, int dflt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (src == NULL) | 
					
						
							|  |  |  |         *target = dflt; | 
					
						
							| 
									
										
										
										
											2012-08-15 23:18:25 +02:00
										 |  |  |     else { | 
					
						
							|  |  |  |         int b = PyObject_IsTrue(src); | 
					
						
							|  |  |  |         if (b < 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         *target = b; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _set_int(const char *name, int *target, PyObject *src, int dflt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (src == NULL) | 
					
						
							|  |  |  |         *target = dflt; | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         long value; | 
					
						
							|  |  |  |         if (!PyLong_CheckExact(src)) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                          "\"%s\" must be an integer", name); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         value = PyLong_AsLong(src); | 
					
						
							|  |  |  |         if (value == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2007-12-04 22:10:37 +00:00
										 |  |  | #if SIZEOF_LONG > SIZEOF_INT
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (value > INT_MAX || value < INT_MIN) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                          "integer out of range for \"%s\"", name); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-12-04 22:10:37 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         *target = (int)value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (src == NULL) | 
					
						
							|  |  |  |         *target = dflt; | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         *target = '\0'; | 
					
						
							|  |  |  |         if (src != Py_None) { | 
					
						
							|  |  |  |             Py_ssize_t len; | 
					
						
							| 
									
										
										
										
											2011-11-21 02:49:52 +01:00
										 |  |  |             len = PyUnicode_GetLength(src); | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             if (len > 1) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                 PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                     "\"%s\" must be an 1-character string", | 
					
						
							|  |  |  |                     name); | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |             /* PyUnicode_READY() is called in PyUnicode_GetLength() */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             if (len > 0) | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |                 *target = PyUnicode_READ_CHAR(src, 0); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _set_str(const char *name, PyObject **target, PyObject *src, const char *dflt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (src == NULL) | 
					
						
							|  |  |  |         *target = PyUnicode_DecodeASCII(dflt, strlen(dflt), NULL); | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (src == Py_None) | 
					
						
							|  |  |  |             *target = NULL; | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |         else if (!PyUnicode_Check(src)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                          "\"%s\" must be a string", name); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |             if (PyUnicode_READY(src) == -1) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             Py_XDECREF(*target); | 
					
						
							|  |  |  |             Py_INCREF(src); | 
					
						
							|  |  |  |             *target = src; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | dialect_check_quoting(int quoting) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-09 09:40:16 +00:00
										 |  |  |     StyleDesc *qs; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (qs = quote_styles; qs->name; qs++) { | 
					
						
							|  |  |  |         if (qs->style == quoting) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, "bad \"quoting\" value"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define D_OFF(x) offsetof(DialectObj, x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMemberDef Dialect_memberlist[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "skipinitialspace",   T_INT, D_OFF(skipinitialspace), READONLY }, | 
					
						
							|  |  |  |     { "doublequote",        T_INT, D_OFF(doublequote), READONLY }, | 
					
						
							|  |  |  |     { "strict",             T_INT, D_OFF(strict), READONLY }, | 
					
						
							|  |  |  |     { NULL } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef Dialect_getsetlist[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "delimiter",          (getter)Dialect_get_delimiter}, | 
					
						
							|  |  |  |     { "escapechar",             (getter)Dialect_get_escapechar}, | 
					
						
							|  |  |  |     { "lineterminator",         (getter)Dialect_get_lineterminator}, | 
					
						
							|  |  |  |     { "quotechar",              (getter)Dialect_get_quotechar}, | 
					
						
							|  |  |  |     { "quoting",                (getter)Dialect_get_quoting}, | 
					
						
							|  |  |  |     {NULL}, | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | Dialect_dealloc(DialectObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_XDECREF(self->lineterminator); | 
					
						
							|  |  |  |     Py_TYPE(self)->tp_free((PyObject *)self); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 17:20:04 +00:00
										 |  |  | static char *dialect_kws[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     "dialect", | 
					
						
							|  |  |  |     "delimiter", | 
					
						
							|  |  |  |     "doublequote", | 
					
						
							|  |  |  |     "escapechar", | 
					
						
							|  |  |  |     "lineterminator", | 
					
						
							|  |  |  |     "quotechar", | 
					
						
							|  |  |  |     "quoting", | 
					
						
							|  |  |  |     "skipinitialspace", | 
					
						
							|  |  |  |     "strict", | 
					
						
							|  |  |  |     NULL | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-11 04:49:53 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *self; | 
					
						
							|  |  |  |     PyObject *ret = NULL; | 
					
						
							|  |  |  |     PyObject *dialect = NULL; | 
					
						
							|  |  |  |     PyObject *delimiter = NULL; | 
					
						
							|  |  |  |     PyObject *doublequote = NULL; | 
					
						
							|  |  |  |     PyObject *escapechar = NULL; | 
					
						
							|  |  |  |     PyObject *lineterminator = NULL; | 
					
						
							|  |  |  |     PyObject *quotechar = NULL; | 
					
						
							|  |  |  |     PyObject *quoting = NULL; | 
					
						
							|  |  |  |     PyObject *skipinitialspace = NULL; | 
					
						
							|  |  |  |     PyObject *strict = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwargs, | 
					
						
							|  |  |  |                                      "|OOOOOOOOO", dialect_kws, | 
					
						
							|  |  |  |                                      &dialect, | 
					
						
							|  |  |  |                                      &delimiter, | 
					
						
							|  |  |  |                                      &doublequote, | 
					
						
							|  |  |  |                                      &escapechar, | 
					
						
							|  |  |  |                                      &lineterminator, | 
					
						
							|  |  |  |                                      "echar, | 
					
						
							|  |  |  |                                      "ing, | 
					
						
							|  |  |  |                                      &skipinitialspace, | 
					
						
							|  |  |  |                                      &strict)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (dialect != NULL) { | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |         if (PyUnicode_Check(dialect)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             dialect = get_dialect_from_registry(dialect); | 
					
						
							|  |  |  |             if (dialect == NULL) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             Py_INCREF(dialect); | 
					
						
							|  |  |  |         /* Can we reuse this instance? */ | 
					
						
							|  |  |  |         if (PyObject_TypeCheck(dialect, &Dialect_Type) && | 
					
						
							|  |  |  |             delimiter == 0 && | 
					
						
							|  |  |  |             doublequote == 0 && | 
					
						
							|  |  |  |             escapechar == 0 && | 
					
						
							|  |  |  |             lineterminator == 0 && | 
					
						
							|  |  |  |             quotechar == 0 && | 
					
						
							|  |  |  |             quoting == 0 && | 
					
						
							|  |  |  |             skipinitialspace == 0 && | 
					
						
							|  |  |  |             strict == 0) | 
					
						
							|  |  |  |             return dialect; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     self = (DialectObj *)type->tp_alloc(type, 0); | 
					
						
							|  |  |  |     if (self == NULL) { | 
					
						
							|  |  |  |         Py_XDECREF(dialect); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->lineterminator = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_XINCREF(delimiter); | 
					
						
							|  |  |  |     Py_XINCREF(doublequote); | 
					
						
							|  |  |  |     Py_XINCREF(escapechar); | 
					
						
							|  |  |  |     Py_XINCREF(lineterminator); | 
					
						
							|  |  |  |     Py_XINCREF(quotechar); | 
					
						
							|  |  |  |     Py_XINCREF(quoting); | 
					
						
							|  |  |  |     Py_XINCREF(skipinitialspace); | 
					
						
							|  |  |  |     Py_XINCREF(strict); | 
					
						
							|  |  |  |     if (dialect != NULL) { | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | #define DIALECT_GETATTR(v, n) \
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (v == NULL) \ | 
					
						
							|  |  |  |             v = PyObject_GetAttrString(dialect, n) | 
					
						
							|  |  |  |         DIALECT_GETATTR(delimiter, "delimiter"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(doublequote, "doublequote"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(escapechar, "escapechar"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(lineterminator, "lineterminator"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(quotechar, "quotechar"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(quoting, "quoting"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(skipinitialspace, "skipinitialspace"); | 
					
						
							|  |  |  |         DIALECT_GETATTR(strict, "strict"); | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* check types and convert to C values */ | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | #define DIASET(meth, name, target, src, dflt) \
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (meth(name, target, src, dflt)) \ | 
					
						
							|  |  |  |         goto err | 
					
						
							|  |  |  |     DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ','); | 
					
						
							|  |  |  |     DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, 1); | 
					
						
							|  |  |  |     DIASET(_set_char, "escapechar", &self->escapechar, escapechar, 0); | 
					
						
							|  |  |  |     DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n"); | 
					
						
							|  |  |  |     DIASET(_set_char, "quotechar", &self->quotechar, quotechar, '"'); | 
					
						
							|  |  |  |     DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL); | 
					
						
							|  |  |  |     DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, 0); | 
					
						
							|  |  |  |     DIASET(_set_bool, "strict", &self->strict, strict, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* validate options */ | 
					
						
							|  |  |  |     if (dialect_check_quoting(self->quoting)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     if (self->delimiter == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "delimiter must be set"); | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (quotechar == Py_None && quoting == NULL) | 
					
						
							|  |  |  |         self->quoting = QUOTE_NONE; | 
					
						
							|  |  |  |     if (self->quoting != QUOTE_NONE && self->quotechar == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "quotechar must be set if quoting enabled"); | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (self->lineterminator == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "lineterminator must be set"); | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = (PyObject *)self; | 
					
						
							|  |  |  |     Py_INCREF(self); | 
					
						
							| 
									
										
										
										
											2005-01-07 04:42:45 +00:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_XDECREF(self); | 
					
						
							|  |  |  |     Py_XDECREF(dialect); | 
					
						
							|  |  |  |     Py_XDECREF(delimiter); | 
					
						
							|  |  |  |     Py_XDECREF(doublequote); | 
					
						
							|  |  |  |     Py_XDECREF(escapechar); | 
					
						
							|  |  |  |     Py_XDECREF(lineterminator); | 
					
						
							|  |  |  |     Py_XDECREF(quotechar); | 
					
						
							|  |  |  |     Py_XDECREF(quoting); | 
					
						
							|  |  |  |     Py_XDECREF(skipinitialspace); | 
					
						
							|  |  |  |     Py_XDECREF(strict); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | PyDoc_STRVAR(Dialect_Type_doc, | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "CSV dialect\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The Dialect type records CSV parsing and generation options.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject Dialect_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  |     "_csv.Dialect",                         /* tp_name */ | 
					
						
							|  |  |  |     sizeof(DialectObj),                     /* tp_basicsize */ | 
					
						
							|  |  |  |     0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  |     /*  methods  */ | 
					
						
							|  |  |  |     (destructor)Dialect_dealloc,            /* tp_dealloc */ | 
					
						
							|  |  |  |     (printfunc)0,                           /* tp_print */ | 
					
						
							|  |  |  |     (getattrfunc)0,                         /* tp_getattr */ | 
					
						
							|  |  |  |     (setattrfunc)0,                         /* tp_setattr */ | 
					
						
							|  |  |  |     0,                                      /* tp_reserved */ | 
					
						
							|  |  |  |     (reprfunc)0,                            /* tp_repr */ | 
					
						
							|  |  |  |     0,                                      /* tp_as_number */ | 
					
						
							|  |  |  |     0,                                      /* tp_as_sequence */ | 
					
						
							|  |  |  |     0,                                      /* tp_as_mapping */ | 
					
						
							|  |  |  |     (hashfunc)0,                            /* tp_hash */ | 
					
						
							|  |  |  |     (ternaryfunc)0,                         /* tp_call */ | 
					
						
							|  |  |  |     (reprfunc)0,                                /* tp_str */ | 
					
						
							|  |  |  |     0,                                      /* tp_getattro */ | 
					
						
							|  |  |  |     0,                                      /* tp_setattro */ | 
					
						
							|  |  |  |     0,                                      /* tp_as_buffer */ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | 
					
						
							|  |  |  |     Dialect_Type_doc,                       /* tp_doc */ | 
					
						
							|  |  |  |     0,                                      /* tp_traverse */ | 
					
						
							|  |  |  |     0,                                      /* tp_clear */ | 
					
						
							|  |  |  |     0,                                      /* tp_richcompare */ | 
					
						
							|  |  |  |     0,                                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     0,                                      /* tp_iter */ | 
					
						
							|  |  |  |     0,                                      /* tp_iternext */ | 
					
						
							|  |  |  |     0,                                          /* tp_methods */ | 
					
						
							|  |  |  |     Dialect_memberlist,                     /* tp_members */ | 
					
						
							|  |  |  |     Dialect_getsetlist,                     /* tp_getset */ | 
					
						
							|  |  |  |     0,                                          /* tp_base */ | 
					
						
							|  |  |  |     0,                                          /* tp_dict */ | 
					
						
							|  |  |  |     0,                                          /* tp_descr_get */ | 
					
						
							|  |  |  |     0,                                          /* tp_descr_set */ | 
					
						
							|  |  |  |     0,                                          /* tp_dictoffset */ | 
					
						
							|  |  |  |     0,                                          /* tp_init */ | 
					
						
							|  |  |  |     0,                                          /* tp_alloc */ | 
					
						
							|  |  |  |     dialect_new,                                /* tp_new */ | 
					
						
							|  |  |  |     0,                                          /* tp_free */ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-11 01:07:23 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Return an instance of the dialect type, given a Python instance or kwarg | 
					
						
							|  |  |  |  * description of the dialect | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _call_dialect(PyObject *dialect_inst, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *ctor_args; | 
					
						
							|  |  |  |     PyObject *dialect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctor_args = Py_BuildValue(dialect_inst ? "(O)" : "()", dialect_inst); | 
					
						
							|  |  |  |     if (ctor_args == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     dialect = PyObject_Call((PyObject *)&Dialect_Type, ctor_args, kwargs); | 
					
						
							|  |  |  |     Py_DECREF(ctor_args); | 
					
						
							|  |  |  |     return dialect; | 
					
						
							| 
									
										
										
										
											2005-01-11 01:07:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * READER | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-01-12 09:45:18 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | parse_save_field(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *field; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     field = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, | 
					
						
							|  |  |  |                                       (void *) self->field, self->field_len); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (field == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     self->field_len = 0; | 
					
						
							|  |  |  |     if (self->numeric_field) { | 
					
						
							|  |  |  |         PyObject *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self->numeric_field = 0; | 
					
						
							|  |  |  |         tmp = PyNumber_Float(field); | 
					
						
							|  |  |  |         Py_DECREF(field); | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         if (tmp == NULL) | 
					
						
							|  |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         field = tmp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyList_Append(self->fields, field); | 
					
						
							|  |  |  |     Py_DECREF(field); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | parse_grow_buff(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (self->field_size == 0) { | 
					
						
							|  |  |  |         self->field_size = 4096; | 
					
						
							|  |  |  |         if (self->field != NULL) | 
					
						
							|  |  |  |             PyMem_Free(self->field); | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         self->field = PyMem_New(Py_UCS4, self->field_size); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         Py_UCS4 *field = self->field; | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |         if (self->field_size > PY_SSIZE_T_MAX / 2) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         self->field_size *= 2; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         self->field = PyMem_Resize(field, Py_UCS4, self->field_size); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (self->field == NULL) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | parse_add_char(ReaderObj *self, Py_UCS4 c) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     if (self->field_len >= _csvstate_global->field_limit) { | 
					
						
							|  |  |  |         PyErr_Format(_csvstate_global->error_obj, "field larger than field limit (%ld)", | 
					
						
							|  |  |  |                      _csvstate_global->field_limit); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (self->field_len == self->field_size && !parse_grow_buff(self)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     self->field[self->field_len++] = c; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | parse_process_char(ReaderObj *self, Py_UCS4 c) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *dialect = self->dialect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (self->state) { | 
					
						
							|  |  |  |     case START_RECORD: | 
					
						
							|  |  |  |         /* start of record */ | 
					
						
							|  |  |  |         if (c == '\0') | 
					
						
							|  |  |  |             /* empty line - return [] */ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         else if (c == '\n' || c == '\r') { | 
					
						
							|  |  |  |             self->state = EAT_CRNL; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* normal character - handle as START_FIELD */ | 
					
						
							|  |  |  |         self->state = START_FIELD; | 
					
						
							|  |  |  |         /* fallthru */ | 
					
						
							|  |  |  |     case START_FIELD: | 
					
						
							|  |  |  |         /* expecting field */ | 
					
						
							|  |  |  |         if (c == '\n' || c == '\r' || c == '\0') { | 
					
						
							|  |  |  |             /* save empty field - return [fields] */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->quotechar && | 
					
						
							|  |  |  |                  dialect->quoting != QUOTE_NONE) { | 
					
						
							|  |  |  |             /* start quoted field */ | 
					
						
							|  |  |  |             self->state = IN_QUOTED_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->escapechar) { | 
					
						
							|  |  |  |             /* possible escaped character */ | 
					
						
							|  |  |  |             self->state = ESCAPED_CHAR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == ' ' && dialect->skipinitialspace) | 
					
						
							|  |  |  |             /* ignore space at start of field */ | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  |         else if (c == dialect->delimiter) { | 
					
						
							|  |  |  |             /* save empty field */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             /* begin new unquoted field */ | 
					
						
							|  |  |  |             if (dialect->quoting == QUOTE_NONNUMERIC) | 
					
						
							|  |  |  |                 self->numeric_field = 1; | 
					
						
							|  |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = IN_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ESCAPED_CHAR: | 
					
						
							| 
									
										
										
										
											2013-03-20 00:15:20 -04:00
										 |  |  |         if (c == '\n' || c=='\r') { | 
					
						
							| 
									
										
										
										
											2013-03-19 22:41:47 -04:00
										 |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = AFTER_ESCAPED_CRNL; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (c == '\0') | 
					
						
							|  |  |  |             c = '\n'; | 
					
						
							|  |  |  |         if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         self->state = IN_FIELD; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 22:41:47 -04:00
										 |  |  |     case AFTER_ESCAPED_CRNL: | 
					
						
							|  |  |  |         if (c == '\0') | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         /*fallthru*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     case IN_FIELD: | 
					
						
							|  |  |  |         /* in unquoted field */ | 
					
						
							|  |  |  |         if (c == '\n' || c == '\r' || c == '\0') { | 
					
						
							|  |  |  |             /* end of line - return [fields] */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->escapechar) { | 
					
						
							|  |  |  |             /* possible escaped character */ | 
					
						
							|  |  |  |             self->state = ESCAPED_CHAR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->delimiter) { | 
					
						
							|  |  |  |             /* save field - wait for new field */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = START_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             /* normal character - save in field */ | 
					
						
							|  |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case IN_QUOTED_FIELD: | 
					
						
							|  |  |  |         /* in quoted field */ | 
					
						
							|  |  |  |         if (c == '\0') | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  |         else if (c == dialect->escapechar) { | 
					
						
							|  |  |  |             /* Possible escape character */ | 
					
						
							|  |  |  |             self->state = ESCAPE_IN_QUOTED_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->quotechar && | 
					
						
							|  |  |  |                  dialect->quoting != QUOTE_NONE) { | 
					
						
							|  |  |  |             if (dialect->doublequote) { | 
					
						
							|  |  |  |                 /* doublequote; " represented by "" */ | 
					
						
							|  |  |  |                 self->state = QUOTE_IN_QUOTED_FIELD; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 /* end of quote part of field */ | 
					
						
							|  |  |  |                 self->state = IN_FIELD; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             /* normal character - save in field */ | 
					
						
							|  |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ESCAPE_IN_QUOTED_FIELD: | 
					
						
							|  |  |  |         if (c == '\0') | 
					
						
							|  |  |  |             c = '\n'; | 
					
						
							|  |  |  |         if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         self->state = IN_QUOTED_FIELD; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUOTE_IN_QUOTED_FIELD: | 
					
						
							|  |  |  |         /* doublequote - seen a quote in an quoted field */ | 
					
						
							|  |  |  |         if (dialect->quoting != QUOTE_NONE && | 
					
						
							|  |  |  |             c == dialect->quotechar) { | 
					
						
							|  |  |  |             /* save "" as " */ | 
					
						
							|  |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = IN_QUOTED_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == dialect->delimiter) { | 
					
						
							|  |  |  |             /* save field - wait for new field */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = START_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (c == '\n' || c == '\r' || c == '\0') { | 
					
						
							|  |  |  |             /* end of line - return [fields] */ | 
					
						
							|  |  |  |             if (parse_save_field(self) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = (c == '\0' ? START_RECORD : EAT_CRNL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (!dialect->strict) { | 
					
						
							|  |  |  |             if (parse_add_char(self, c) < 0) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             self->state = IN_FIELD; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             /* illegal */ | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |             PyErr_Format(_csvstate_global->error_obj, "'%c' expected after '%c'", | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                             dialect->delimiter, | 
					
						
							|  |  |  |                             dialect->quotechar); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case EAT_CRNL: | 
					
						
							|  |  |  |         if (c == '\n' || c == '\r') | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  |         else if (c == '\0') | 
					
						
							|  |  |  |             self->state = START_RECORD; | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |             PyErr_Format(_csvstate_global->error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | parse_reset(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_XDECREF(self->fields); | 
					
						
							|  |  |  |     self->fields = PyList_New(0); | 
					
						
							|  |  |  |     if (self->fields == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     self->field_len = 0; | 
					
						
							|  |  |  |     self->state = START_RECORD; | 
					
						
							|  |  |  |     self->numeric_field = 0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | Reader_iternext(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *fields = NULL; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     Py_UCS4 c; | 
					
						
							|  |  |  |     Py_ssize_t pos, linelen; | 
					
						
							|  |  |  |     unsigned int kind; | 
					
						
							|  |  |  |     void *data; | 
					
						
							|  |  |  |     PyObject *lineobj; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (parse_reset(self) < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         lineobj = PyIter_Next(self->input_iter); | 
					
						
							|  |  |  |         if (lineobj == NULL) { | 
					
						
							|  |  |  |             /* End of input OR exception */ | 
					
						
							| 
									
										
										
										
											2012-09-25 02:30:27 -07:00
										 |  |  |             if (!PyErr_Occurred() && (self->field_len != 0 || | 
					
						
							|  |  |  |                                       self->state == IN_QUOTED_FIELD)) { | 
					
						
							|  |  |  |                 if (self->dialect->strict) | 
					
						
							| 
									
										
										
										
											2012-09-25 02:37:20 -07:00
										 |  |  |                     PyErr_SetString(_csvstate_global->error_obj, | 
					
						
							|  |  |  |                                     "unexpected end of data"); | 
					
						
							| 
									
										
										
										
											2012-09-25 02:30:27 -07:00
										 |  |  |                 else if (parse_save_field(self) >= 0) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!PyUnicode_Check(lineobj)) { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |             PyErr_Format(_csvstate_global->error_obj, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                          "iterator should return strings, " | 
					
						
							|  |  |  |                          "not %.200s " | 
					
						
							|  |  |  |                          "(did you open the file in text mode?)", | 
					
						
							|  |  |  |                          lineobj->ob_type->tp_name | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             Py_DECREF(lineobj); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |         if (PyUnicode_READY(lineobj) == -1) { | 
					
						
							|  |  |  |             Py_DECREF(lineobj); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         ++self->line_num; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         kind = PyUnicode_KIND(lineobj); | 
					
						
							|  |  |  |         data = PyUnicode_DATA(lineobj); | 
					
						
							|  |  |  |         pos = 0; | 
					
						
							|  |  |  |         linelen = PyUnicode_GET_LENGTH(lineobj); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         while (linelen--) { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             c = PyUnicode_READ(kind, data, pos); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             if (c == '\0') { | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  |                 Py_DECREF(lineobj); | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |                 PyErr_Format(_csvstate_global->error_obj, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                              "line contains NULL byte"); | 
					
						
							|  |  |  |                 goto err; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (parse_process_char(self, c) < 0) { | 
					
						
							|  |  |  |                 Py_DECREF(lineobj); | 
					
						
							|  |  |  |                 goto err; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             pos++; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(lineobj); | 
					
						
							|  |  |  |         if (parse_process_char(self, 0) < 0) | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |     } while (self->state != START_RECORD); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     fields = self->fields; | 
					
						
							|  |  |  |     self->fields = NULL; | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return fields; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | Reader_dealloc(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_GC_UnTrack(self); | 
					
						
							|  |  |  |     Py_XDECREF(self->dialect); | 
					
						
							|  |  |  |     Py_XDECREF(self->input_iter); | 
					
						
							|  |  |  |     Py_XDECREF(self->fields); | 
					
						
							|  |  |  |     if (self->field != NULL) | 
					
						
							|  |  |  |         PyMem_Free(self->field); | 
					
						
							|  |  |  |     PyObject_GC_Del(self); | 
					
						
							| 
									
										
										
										
											2003-04-14 02:20:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Reader_traverse(ReaderObj *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_VISIT(self->dialect); | 
					
						
							|  |  |  |     Py_VISIT(self->input_iter); | 
					
						
							|  |  |  |     Py_VISIT(self->fields); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-04-14 02:20:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Reader_clear(ReaderObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_CLEAR(self->dialect); | 
					
						
							|  |  |  |     Py_CLEAR(self->input_iter); | 
					
						
							|  |  |  |     Py_CLEAR(self->fields); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(Reader_Type_doc, | 
					
						
							|  |  |  | "CSV reader\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "Reader objects are responsible for reading and parsing tabular data\n" | 
					
						
							|  |  |  | "in CSV format.\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMethodDef Reader_methods[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { NULL, NULL } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | #define R_OFF(x) offsetof(ReaderObj, x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMemberDef Reader_memberlist[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "dialect", T_OBJECT, R_OFF(dialect), READONLY }, | 
					
						
							|  |  |  |     { "line_num", T_ULONG, R_OFF(line_num), READONLY }, | 
					
						
							|  |  |  |     { NULL } | 
					
						
							| 
									
										
										
										
											2005-01-13 11:30:54 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject Reader_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  |     "_csv.reader",                          /*tp_name*/ | 
					
						
							|  |  |  |     sizeof(ReaderObj),                      /*tp_basicsize*/ | 
					
						
							|  |  |  |     0,                                      /*tp_itemsize*/ | 
					
						
							|  |  |  |     /* methods */ | 
					
						
							|  |  |  |     (destructor)Reader_dealloc,             /*tp_dealloc*/ | 
					
						
							|  |  |  |     (printfunc)0,                           /*tp_print*/ | 
					
						
							|  |  |  |     (getattrfunc)0,                         /*tp_getattr*/ | 
					
						
							|  |  |  |     (setattrfunc)0,                         /*tp_setattr*/ | 
					
						
							|  |  |  |     0,                                     /*tp_reserved*/ | 
					
						
							|  |  |  |     (reprfunc)0,                            /*tp_repr*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_number*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_sequence*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_mapping*/ | 
					
						
							|  |  |  |     (hashfunc)0,                            /*tp_hash*/ | 
					
						
							|  |  |  |     (ternaryfunc)0,                         /*tp_call*/ | 
					
						
							|  |  |  |     (reprfunc)0,                                /*tp_str*/ | 
					
						
							|  |  |  |     0,                                      /*tp_getattro*/ | 
					
						
							|  |  |  |     0,                                      /*tp_setattro*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_buffer*/ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | 
					
						
							|  |  |  |         Py_TPFLAGS_HAVE_GC,                     /*tp_flags*/ | 
					
						
							|  |  |  |     Reader_Type_doc,                        /*tp_doc*/ | 
					
						
							|  |  |  |     (traverseproc)Reader_traverse,          /*tp_traverse*/ | 
					
						
							|  |  |  |     (inquiry)Reader_clear,                  /*tp_clear*/ | 
					
						
							|  |  |  |     0,                                      /*tp_richcompare*/ | 
					
						
							|  |  |  |     0,                                      /*tp_weaklistoffset*/ | 
					
						
							|  |  |  |     PyObject_SelfIter,                          /*tp_iter*/ | 
					
						
							|  |  |  |     (getiterfunc)Reader_iternext,           /*tp_iternext*/ | 
					
						
							|  |  |  |     Reader_methods,                         /*tp_methods*/ | 
					
						
							|  |  |  |     Reader_memberlist,                      /*tp_members*/ | 
					
						
							|  |  |  |     0,                                      /*tp_getset*/ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject * iterator, * dialect = NULL; | 
					
						
							|  |  |  |     ReaderObj * self = PyObject_GC_New(ReaderObj, &Reader_Type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!self) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     self->dialect = NULL; | 
					
						
							|  |  |  |     self->fields = NULL; | 
					
						
							|  |  |  |     self->input_iter = NULL; | 
					
						
							|  |  |  |     self->field = NULL; | 
					
						
							|  |  |  |     self->field_size = 0; | 
					
						
							|  |  |  |     self->line_num = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (parse_reset(self) < 0) { | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_UnpackTuple(args, "", 1, 2, &iterator, &dialect)) { | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->input_iter = PyObject_GetIter(iterator); | 
					
						
							|  |  |  |     if (self->input_iter == NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "argument 1 must be an iterator"); | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); | 
					
						
							|  |  |  |     if (self->dialect == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject_GC_Track(self); | 
					
						
							|  |  |  |     return (PyObject *)self; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * WRITER | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* ---------------------------------------------------------------- */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | join_reset(WriterObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     self->rec_len = 0; | 
					
						
							|  |  |  |     self->num_fields = 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MEM_INCR 32768
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Calculate new record length or append field to record.  Return new
 | 
					
						
							|  |  |  |  * record length. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | join_append_data(WriterObj *self, unsigned int field_kind, void *field_data, | 
					
						
							|  |  |  |                  Py_ssize_t field_len, int quote_empty, int *quoted, | 
					
						
							|  |  |  |                  int copy_phase) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *dialect = self->dialect; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     Py_ssize_t rec_len; | 
					
						
							| 
									
										
										
										
											2005-01-12 07:44:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define ADDCH(c) \
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     do {\ | 
					
						
							|  |  |  |         if (copy_phase) \ | 
					
						
							|  |  |  |             self->rec[rec_len] = c;\ | 
					
						
							|  |  |  |         rec_len++;\ | 
					
						
							|  |  |  |     } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rec_len = self->rec_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If this is not the first field we need a field separator */ | 
					
						
							|  |  |  |     if (self->num_fields > 0) | 
					
						
							|  |  |  |         ADDCH(dialect->delimiter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Handle preceding quote */ | 
					
						
							|  |  |  |     if (copy_phase && *quoted) | 
					
						
							|  |  |  |         ADDCH(dialect->quotechar); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Copy/count field data */ | 
					
						
							|  |  |  |     /* If field is null just pass over */ | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     for (i = 0; field_data && (i < field_len); i++) { | 
					
						
							|  |  |  |         Py_UCS4 c = PyUnicode_READ(field_kind, field_data, i); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         int want_escape = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (c == dialect->delimiter || | 
					
						
							|  |  |  |             c == dialect->escapechar || | 
					
						
							|  |  |  |             c == dialect->quotechar  || | 
					
						
							| 
									
										
										
										
											2011-11-01 18:42:23 +01:00
										 |  |  |             PyUnicode_FindChar( | 
					
						
							|  |  |  |                 dialect->lineterminator, c, 0, | 
					
						
							|  |  |  |                 PyUnicode_GET_LENGTH(dialect->lineterminator), 1) >= 0) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             if (dialect->quoting == QUOTE_NONE) | 
					
						
							|  |  |  |                 want_escape = 1; | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 if (c == dialect->quotechar) { | 
					
						
							|  |  |  |                     if (dialect->doublequote) | 
					
						
							|  |  |  |                         ADDCH(dialect->quotechar); | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         want_escape = 1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (!want_escape) | 
					
						
							|  |  |  |                     *quoted = 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (want_escape) { | 
					
						
							|  |  |  |                 if (!dialect->escapechar) { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |                     PyErr_Format(_csvstate_global->error_obj, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                                  "need to escape, but no escapechar set"); | 
					
						
							|  |  |  |                     return -1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 ADDCH(dialect->escapechar); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Copy field character into record buffer.
 | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         ADDCH(c); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If field is empty check if it needs to be quoted.
 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (i == 0 && quote_empty) { | 
					
						
							|  |  |  |         if (dialect->quoting == QUOTE_NONE) { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |             PyErr_Format(_csvstate_global->error_obj, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                 "single empty field record must be quoted"); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             *quoted = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*quoted) { | 
					
						
							|  |  |  |         if (copy_phase) | 
					
						
							|  |  |  |             ADDCH(dialect->quotechar); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             rec_len += 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rec_len; | 
					
						
							| 
									
										
										
										
											2005-01-12 07:44:42 +00:00
										 |  |  | #undef ADDCH
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  | join_check_rec_size(WriterObj *self, Py_ssize_t rec_len) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-18 00:47:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     if (rec_len < 0 || rec_len > PY_SSIZE_T_MAX - MEM_INCR) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (rec_len > self->rec_size) { | 
					
						
							|  |  |  |         if (self->rec_size == 0) { | 
					
						
							|  |  |  |             self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR; | 
					
						
							|  |  |  |             if (self->rec != NULL) | 
					
						
							|  |  |  |                 PyMem_Free(self->rec); | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             self->rec = PyMem_New(Py_UCS4, self->rec_size); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             Py_UCS4* old_rec = self->rec; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             self->rec = PyMem_Resize(old_rec, Py_UCS4, self->rec_size); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             if (self->rec == NULL) | 
					
						
							|  |  |  |                 PyMem_Free(old_rec); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (self->rec == NULL) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  | join_append(WriterObj *self, PyObject *field, int *quoted, int quote_empty) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     unsigned int field_kind = -1; | 
					
						
							|  |  |  |     void *field_data = NULL; | 
					
						
							|  |  |  |     Py_ssize_t field_len = 0; | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     Py_ssize_t rec_len; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     if (field != NULL) { | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |         if (PyUnicode_READY(field) == -1) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |         field_kind = PyUnicode_KIND(field); | 
					
						
							|  |  |  |         field_data = PyUnicode_DATA(field); | 
					
						
							|  |  |  |         field_len = PyUnicode_GET_LENGTH(field); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     rec_len = join_append_data(self, field_kind, field_data, field_len, | 
					
						
							|  |  |  |                                quote_empty, quoted, 0); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (rec_len < 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* grow record buffer if necessary */ | 
					
						
							|  |  |  |     if (!join_check_rec_size(self, rec_len)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     self->rec_len = join_append_data(self, field_kind, field_data, field_len, | 
					
						
							|  |  |  |                                      quote_empty, quoted, 1); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     self->num_fields++; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | join_append_lineterminator(WriterObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     Py_ssize_t terminator_len, i; | 
					
						
							|  |  |  |     unsigned int term_kind; | 
					
						
							|  |  |  |     void *term_data; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     terminator_len = PyUnicode_GET_LENGTH(self->dialect->lineterminator); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (terminator_len == -1) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* grow record buffer if necessary */ | 
					
						
							|  |  |  |     if (!join_check_rec_size(self, self->rec_len + terminator_len)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |     term_kind = PyUnicode_KIND(self->dialect->lineterminator); | 
					
						
							|  |  |  |     term_data = PyUnicode_DATA(self->dialect->lineterminator); | 
					
						
							|  |  |  |     for (i = 0; i < terminator_len; i++) | 
					
						
							|  |  |  |         self->rec[self->rec_len + i] = PyUnicode_READ(term_kind, term_data, i); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     self->rec_len += terminator_len; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_writerow_doc, | 
					
						
							| 
									
										
										
										
											2003-04-12 18:57:52 +00:00
										 |  |  | "writerow(sequence)\n" | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2003-04-12 18:57:52 +00:00
										 |  |  | "Construct and write a CSV record from a sequence of fields.  Non-string\n" | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "elements will be converted to string."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | csv_writerow(WriterObj *self, PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DialectObj *dialect = self->dialect; | 
					
						
							| 
									
										
										
										
											2010-08-15 18:51:10 +00:00
										 |  |  |     Py_ssize_t len, i; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:35:30 +02:00
										 |  |  |     PyObject *line, *result; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!PySequence_Check(seq)) | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |         return PyErr_Format(_csvstate_global->error_obj, "sequence expected"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     len = PySequence_Length(seq); | 
					
						
							|  |  |  |     if (len < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Join all fields in internal buffer.
 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     join_reset(self); | 
					
						
							|  |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         PyObject *field; | 
					
						
							|  |  |  |         int append_ok; | 
					
						
							|  |  |  |         int quoted; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         field = PySequence_GetItem(seq, i); | 
					
						
							|  |  |  |         if (field == NULL) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (dialect->quoting) { | 
					
						
							|  |  |  |         case QUOTE_NONNUMERIC: | 
					
						
							|  |  |  |             quoted = !PyNumber_Check(field); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case QUOTE_ALL: | 
					
						
							|  |  |  |             quoted = 1; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             quoted = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (PyUnicode_Check(field)) { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             append_ok = join_append(self, field, "ed, len == 1); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             Py_DECREF(field); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (field == Py_None) { | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             append_ok = join_append(self, NULL, "ed, len == 1); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             Py_DECREF(field); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             PyObject *str; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             str = PyObject_Str(field); | 
					
						
							|  |  |  |             Py_DECREF(field); | 
					
						
							|  |  |  |             if (str == NULL) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							| 
									
										
										
										
											2011-10-07 04:26:55 +02:00
										 |  |  |             append_ok = join_append(self, str, "ed, len == 1); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             Py_DECREF(str); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!append_ok) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add line terminator.
 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (!join_append_lineterminator(self)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 04:35:30 +02:00
										 |  |  |     line = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, | 
					
						
							|  |  |  |                                      (void *) self->rec, self->rec_len); | 
					
						
							|  |  |  |     if (line == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     result = PyObject_CallFunctionObjArgs(self->writeline, line, NULL); | 
					
						
							|  |  |  |     Py_DECREF(line); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-12 18:57:52 +00:00
										 |  |  | PyDoc_STRVAR(csv_writerows_doc, | 
					
						
							|  |  |  | "writerows(sequence of sequences)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "Construct and write a series of sequences to a csv file.  Non-string\n" | 
					
						
							|  |  |  | "elements will be converted to string."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | csv_writerows(WriterObj *self, PyObject *seqseq) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *row_iter, *row_obj, *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row_iter = PyObject_GetIter(seqseq); | 
					
						
							|  |  |  |     if (row_iter == NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "writerows() argument must be iterable"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while ((row_obj = PyIter_Next(row_iter))) { | 
					
						
							|  |  |  |         result = csv_writerow(self, row_obj); | 
					
						
							|  |  |  |         Py_DECREF(row_obj); | 
					
						
							|  |  |  |         if (!result) { | 
					
						
							|  |  |  |             Py_DECREF(row_iter); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         else | 
					
						
							|  |  |  |              Py_DECREF(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(row_iter); | 
					
						
							|  |  |  |     if (PyErr_Occurred()) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     Py_INCREF(Py_None); | 
					
						
							|  |  |  |     return Py_None; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMethodDef Writer_methods[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc}, | 
					
						
							|  |  |  |     { "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc}, | 
					
						
							|  |  |  |     { NULL, NULL } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define W_OFF(x) offsetof(WriterObj, x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMemberDef Writer_memberlist[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "dialect", T_OBJECT, W_OFF(dialect), READONLY }, | 
					
						
							|  |  |  |     { NULL } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | Writer_dealloc(WriterObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_GC_UnTrack(self); | 
					
						
							|  |  |  |     Py_XDECREF(self->dialect); | 
					
						
							|  |  |  |     Py_XDECREF(self->writeline); | 
					
						
							|  |  |  |     if (self->rec != NULL) | 
					
						
							|  |  |  |         PyMem_Free(self->rec); | 
					
						
							|  |  |  |     PyObject_GC_Del(self); | 
					
						
							| 
									
										
										
										
											2003-04-14 02:20:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Writer_traverse(WriterObj *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_VISIT(self->dialect); | 
					
						
							|  |  |  |     Py_VISIT(self->writeline); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-04-14 02:20:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | Writer_clear(WriterObj *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_CLEAR(self->dialect); | 
					
						
							|  |  |  |     Py_CLEAR(self->writeline); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | PyDoc_STRVAR(Writer_Type_doc, | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "CSV writer\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "Writer objects are responsible for generating tabular data\n" | 
					
						
							|  |  |  | "in CSV format from sequence input.\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject Writer_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  |     "_csv.writer",                          /*tp_name*/ | 
					
						
							|  |  |  |     sizeof(WriterObj),                      /*tp_basicsize*/ | 
					
						
							|  |  |  |     0,                                      /*tp_itemsize*/ | 
					
						
							|  |  |  |     /* methods */ | 
					
						
							|  |  |  |     (destructor)Writer_dealloc,             /*tp_dealloc*/ | 
					
						
							|  |  |  |     (printfunc)0,                           /*tp_print*/ | 
					
						
							|  |  |  |     (getattrfunc)0,                         /*tp_getattr*/ | 
					
						
							|  |  |  |     (setattrfunc)0,                         /*tp_setattr*/ | 
					
						
							|  |  |  |     0,                                      /*tp_reserved*/ | 
					
						
							|  |  |  |     (reprfunc)0,                            /*tp_repr*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_number*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_sequence*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_mapping*/ | 
					
						
							|  |  |  |     (hashfunc)0,                            /*tp_hash*/ | 
					
						
							|  |  |  |     (ternaryfunc)0,                         /*tp_call*/ | 
					
						
							|  |  |  |     (reprfunc)0,                            /*tp_str*/ | 
					
						
							|  |  |  |     0,                                      /*tp_getattro*/ | 
					
						
							|  |  |  |     0,                                      /*tp_setattro*/ | 
					
						
							|  |  |  |     0,                                      /*tp_as_buffer*/ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | 
					
						
							|  |  |  |         Py_TPFLAGS_HAVE_GC,                     /*tp_flags*/ | 
					
						
							|  |  |  |     Writer_Type_doc, | 
					
						
							|  |  |  |     (traverseproc)Writer_traverse,          /*tp_traverse*/ | 
					
						
							|  |  |  |     (inquiry)Writer_clear,                  /*tp_clear*/ | 
					
						
							|  |  |  |     0,                                      /*tp_richcompare*/ | 
					
						
							|  |  |  |     0,                                      /*tp_weaklistoffset*/ | 
					
						
							|  |  |  |     (getiterfunc)0,                         /*tp_iter*/ | 
					
						
							|  |  |  |     (getiterfunc)0,                         /*tp_iternext*/ | 
					
						
							|  |  |  |     Writer_methods,                         /*tp_methods*/ | 
					
						
							|  |  |  |     Writer_memberlist,                      /*tp_members*/ | 
					
						
							|  |  |  |     0,                                      /*tp_getset*/ | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject * output_file, * dialect = NULL; | 
					
						
							|  |  |  |     WriterObj * self = PyObject_GC_New(WriterObj, &Writer_Type); | 
					
						
							| 
									
										
										
										
											2011-10-14 10:20:37 +02:00
										 |  |  |     _Py_IDENTIFIER(write); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!self) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     self->dialect = NULL; | 
					
						
							|  |  |  |     self->writeline = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     self->rec = NULL; | 
					
						
							|  |  |  |     self->rec_size = 0; | 
					
						
							|  |  |  |     self->rec_len = 0; | 
					
						
							|  |  |  |     self->num_fields = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_UnpackTuple(args, "", 1, 2, &output_file, &dialect)) { | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-10-10 18:11:30 +02:00
										 |  |  |     self->writeline = _PyObject_GetAttrId(output_file, &PyId_write); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (self->writeline == NULL || !PyCallable_Check(self->writeline)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "argument 1 must have a \"write\" method"); | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); | 
					
						
							|  |  |  |     if (self->dialect == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(self); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject_GC_Track(self); | 
					
						
							|  |  |  |     return (PyObject *)self; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * DIALECT REGISTRY | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | csv_list_dialects(PyObject *module, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     return PyDict_Keys(_csvstate_global->dialects); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-01-11 01:28:33 +00:00
										 |  |  | csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *name_obj, *dialect_obj = NULL; | 
					
						
							|  |  |  |     PyObject *dialect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |     if (!PyUnicode_Check(name_obj)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |                         "dialect name must be a string"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-11-02 14:44:20 +01:00
										 |  |  |     if (PyUnicode_READY(name_obj) == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     dialect = _call_dialect(dialect_obj, kwargs); | 
					
						
							|  |  |  |     if (dialect == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     if (PyDict_SetItem(_csvstate_global->dialects, name_obj, dialect) < 0) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_DECREF(dialect); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(dialect); | 
					
						
							|  |  |  |     Py_INCREF(Py_None); | 
					
						
							|  |  |  |     return Py_None; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-04-12 19:17:14 +00:00
										 |  |  | csv_unregister_dialect(PyObject *module, PyObject *name_obj) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     if (PyDict_DelItem(_csvstate_global->dialects, name_obj) < 0) | 
					
						
							|  |  |  |         return PyErr_Format(_csvstate_global->error_obj, "unknown dialect"); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_INCREF(Py_None); | 
					
						
							|  |  |  |     return Py_None; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-04-12 19:17:14 +00:00
										 |  |  | csv_get_dialect(PyObject *module, PyObject *name_obj) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return get_dialect_from_registry(name_obj); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-01-12 03:45:10 +00:00
										 |  |  | csv_field_size_limit(PyObject *module, PyObject *args) | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *new_limit = NULL; | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     long old_limit = _csvstate_global->field_limit; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (new_limit != NULL) { | 
					
						
							|  |  |  |         if (!PyLong_CheckExact(new_limit)) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                          "limit must be an integer"); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |         _csvstate_global->field_limit = PyLong_AsLong(new_limit); | 
					
						
							|  |  |  |         if (_csvstate_global->field_limit == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |             _csvstate_global->field_limit = old_limit; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyLong_FromLong(old_limit); | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * MODULE | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_module_doc, | 
					
						
							|  |  |  | "CSV parsing and writing.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "This module provides classes that assist in the reading and writing\n" | 
					
						
							|  |  |  | "of Comma Separated Value (CSV) files, and implements the interface\n" | 
					
						
							|  |  |  | "described by PEP 305.  Although many CSV files are simple to parse,\n" | 
					
						
							|  |  |  | "the format is not formally defined by a stable specification and\n" | 
					
						
							|  |  |  | "is subtle enough that parsing lines of a CSV file with something\n" | 
					
						
							|  |  |  | "like line.split(\",\") is bound to fail.  The module supports three\n" | 
					
						
							|  |  |  | "basic APIs: reading, writing, and registration of dialects.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "DIALECT REGISTRATION:\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "Readers and writers support a dialect argument, which is a convenient\n" | 
					
						
							|  |  |  | "handle on a group of settings.  When the dialect argument is a string,\n" | 
					
						
							|  |  |  | "it identifies one of the dialects previously registered with the module.\n" | 
					
						
							|  |  |  | "If it is a class or instance, the attributes of the argument are used as\n" | 
					
						
							|  |  |  | "the settings for the reader or writer:\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "    class excel:\n" | 
					
						
							|  |  |  | "        delimiter = ','\n" | 
					
						
							|  |  |  | "        quotechar = '\"'\n" | 
					
						
							|  |  |  | "        escapechar = None\n" | 
					
						
							|  |  |  | "        doublequote = True\n" | 
					
						
							|  |  |  | "        skipinitialspace = False\n" | 
					
						
							| 
									
										
										
										
											2004-08-15 12:23:10 +00:00
										 |  |  | "        lineterminator = '\\r\\n'\n" | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "        quoting = QUOTE_MINIMAL\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "SETTINGS:\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "    * quotechar - specifies a one-character string to use as the \n" | 
					
						
							|  |  |  | "        quoting character.  It defaults to '\"'.\n" | 
					
						
							|  |  |  | "    * delimiter - specifies a one-character string to use as the \n" | 
					
						
							|  |  |  | "        field separator.  It defaults to ','.\n" | 
					
						
							|  |  |  | "    * skipinitialspace - specifies how to interpret whitespace which\n" | 
					
						
							|  |  |  | "        immediately follows a delimiter.  It defaults to False, which\n" | 
					
						
							|  |  |  | "        means that whitespace immediately following a delimiter is part\n" | 
					
						
							|  |  |  | "        of the following field.\n" | 
					
						
							|  |  |  | "    * lineterminator -  specifies the character sequence which should \n" | 
					
						
							|  |  |  | "        terminate rows.\n" | 
					
						
							|  |  |  | "    * quoting - controls when quotes should be generated by the writer.\n" | 
					
						
							|  |  |  | "        It can take on any of the following module constants:\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "        csv.QUOTE_MINIMAL means only when required, for example, when a\n" | 
					
						
							|  |  |  | "            field contains either the quotechar or the delimiter\n" | 
					
						
							|  |  |  | "        csv.QUOTE_ALL means that quotes are always placed around fields.\n" | 
					
						
							|  |  |  | "        csv.QUOTE_NONNUMERIC means that quotes are always placed around\n" | 
					
						
							| 
									
										
										
										
											2003-12-02 18:57:47 +00:00
										 |  |  | "            fields which do not parse as integers or floating point\n" | 
					
						
							|  |  |  | "            numbers.\n" | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "        csv.QUOTE_NONE means that quotes are never placed around fields.\n" | 
					
						
							|  |  |  | "    * escapechar - specifies a one-character string used to escape \n" | 
					
						
							|  |  |  | "        the delimiter when quoting is set to QUOTE_NONE.\n" | 
					
						
							|  |  |  | "    * doublequote - controls the handling of quotes inside fields.  When\n" | 
					
						
							|  |  |  | "        True, two consecutive quotes are interpreted as one during read,\n" | 
					
						
							|  |  |  | "        and when writing, each quote character embedded in the data is\n" | 
					
						
							|  |  |  | "        written as two quotes\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_reader_doc, | 
					
						
							|  |  |  | "    csv_reader = reader(iterable [, dialect='excel']\n" | 
					
						
							|  |  |  | "                        [optional keyword args])\n" | 
					
						
							|  |  |  | "    for row in csv_reader:\n" | 
					
						
							|  |  |  | "        process(row)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The \"iterable\" argument can be any object that returns a line\n" | 
					
						
							|  |  |  | "of input for each iteration, such as a file object or a list.  The\n" | 
					
						
							|  |  |  | "optional \"dialect\" parameter is discussed below.  The function\n" | 
					
						
							|  |  |  | "also accepts optional keyword arguments which override settings\n" | 
					
						
							|  |  |  | "provided by the dialect.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The returned object is an iterator.  Each iteration returns a row\n" | 
					
						
							| 
									
										
										
										
											2004-08-15 12:23:10 +00:00
										 |  |  | "of the CSV file (which can span multiple input lines):\n"); | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_writer_doc, | 
					
						
							|  |  |  | "    csv_writer = csv.writer(fileobj [, dialect='excel']\n" | 
					
						
							|  |  |  | "                            [optional keyword args])\n" | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | "    for row in sequence:\n" | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | "        csv_writer.writerow(row)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "    [or]\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "    csv_writer = csv.writer(fileobj [, dialect='excel']\n" | 
					
						
							|  |  |  | "                            [optional keyword args])\n" | 
					
						
							|  |  |  | "    csv_writer.writerows(rows)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The \"fileobj\" argument can be any object that supports the file API.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_list_dialects_doc, | 
					
						
							|  |  |  | "Return a list of all know dialect names.\n" | 
					
						
							|  |  |  | "    names = csv.list_dialects()"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_get_dialect_doc, | 
					
						
							|  |  |  | "Return the dialect instance associated with name.\n" | 
					
						
							|  |  |  | "    dialect = csv.get_dialect(name)"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_register_dialect_doc, | 
					
						
							|  |  |  | "Create a mapping from a string name to a dialect class.\n" | 
					
						
							|  |  |  | "    dialect = csv.register_dialect(name, dialect)"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(csv_unregister_dialect_doc, | 
					
						
							|  |  |  | "Delete the name/dialect mapping associated with a string name.\n" | 
					
						
							|  |  |  | "    csv.unregister_dialect(name)"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-12 03:45:10 +00:00
										 |  |  | PyDoc_STRVAR(csv_field_size_limit_doc, | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | "Sets an upper limit on parsed fields.\n" | 
					
						
							| 
									
										
										
										
											2005-01-12 03:45:10 +00:00
										 |  |  | "    csv.field_size_limit([limit])\n" | 
					
						
							| 
									
										
										
										
											2005-01-11 07:32:02 +00:00
										 |  |  | "\n" | 
					
						
							|  |  |  | "Returns old limit. If limit is not given, no new limit is set and\n" | 
					
						
							|  |  |  | "the old limit is returned"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | static struct PyMethodDef csv_methods[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { "reader", (PyCFunction)csv_reader, | 
					
						
							|  |  |  |         METH_VARARGS | METH_KEYWORDS, csv_reader_doc}, | 
					
						
							|  |  |  |     { "writer", (PyCFunction)csv_writer, | 
					
						
							|  |  |  |         METH_VARARGS | METH_KEYWORDS, csv_writer_doc}, | 
					
						
							|  |  |  |     { "list_dialects", (PyCFunction)csv_list_dialects, | 
					
						
							|  |  |  |         METH_NOARGS, csv_list_dialects_doc}, | 
					
						
							|  |  |  |     { "register_dialect", (PyCFunction)csv_register_dialect, | 
					
						
							|  |  |  |         METH_VARARGS | METH_KEYWORDS, csv_register_dialect_doc}, | 
					
						
							|  |  |  |     { "unregister_dialect", (PyCFunction)csv_unregister_dialect, | 
					
						
							|  |  |  |         METH_O, csv_unregister_dialect_doc}, | 
					
						
							|  |  |  |     { "get_dialect", (PyCFunction)csv_get_dialect, | 
					
						
							|  |  |  |         METH_O, csv_get_dialect_doc}, | 
					
						
							|  |  |  |     { "field_size_limit", (PyCFunction)csv_field_size_limit, | 
					
						
							|  |  |  |         METH_VARARGS, csv_field_size_limit_doc}, | 
					
						
							|  |  |  |     { NULL, NULL } | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | static struct PyModuleDef _csvmodule = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     "_csv", | 
					
						
							|  |  |  |     csv_module_doc, | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     sizeof(_csvstate), | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     csv_methods, | 
					
						
							|  |  |  |     NULL, | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     _csv_traverse, | 
					
						
							|  |  |  |     _csv_clear, | 
					
						
							|  |  |  |     _csv_free | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | PyMODINIT_FUNC | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | PyInit__csv(void) | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *module; | 
					
						
							|  |  |  |     StyleDesc *style; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyType_Ready(&Dialect_Type) < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyType_Ready(&Reader_Type) < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyType_Ready(&Writer_Type) < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Create the module and add the functions */ | 
					
						
							|  |  |  |     module = PyModule_Create(&_csvmodule); | 
					
						
							|  |  |  |     if (module == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add version to the module. */ | 
					
						
							|  |  |  |     if (PyModule_AddStringConstant(module, "__version__", | 
					
						
							|  |  |  |                                    MODULE_VERSION) == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     /* Set the field limit */ | 
					
						
							|  |  |  |     _csvstate(module)->field_limit = 128 * 1024; | 
					
						
							|  |  |  |     /* Do I still need to add this var to the Module Dict? */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* Add _dialects dictionary */ | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     _csvstate(module)->dialects = PyDict_New(); | 
					
						
							|  |  |  |     if (_csvstate(module)->dialects == NULL) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     Py_INCREF(_csvstate(module)->dialects); | 
					
						
							|  |  |  |     if (PyModule_AddObject(module, "_dialects", _csvstate(module)->dialects)) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add quote styles into dictionary */ | 
					
						
							|  |  |  |     for (style = quote_styles; style->name; style++) { | 
					
						
							|  |  |  |         if (PyModule_AddIntConstant(module, style->name, | 
					
						
							|  |  |  |                                     style->style) == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add the Dialect type */ | 
					
						
							|  |  |  |     Py_INCREF(&Dialect_Type); | 
					
						
							|  |  |  |     if (PyModule_AddObject(module, "Dialect", (PyObject *)&Dialect_Type)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add the CSV exception object to the module. */ | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     _csvstate(module)->error_obj = PyErr_NewException("_csv.Error", NULL, NULL); | 
					
						
							|  |  |  |     if (_csvstate(module)->error_obj == NULL) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2012-05-16 11:33:08 +02:00
										 |  |  |     Py_INCREF(_csvstate(module)->error_obj); | 
					
						
							|  |  |  |     PyModule_AddObject(module, "Error", _csvstate(module)->error_obj); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return module; | 
					
						
							| 
									
										
										
										
											2003-03-20 23:29:12 +00:00
										 |  |  | } |