Index: Modules/_csv.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_csv.c,v retrieving revision 1.38 diff -c -c -r1.38 _csv.c *** Modules/_csv.c 15 Jun 2005 13:35:08 -0000 1.38 --- Modules/_csv.c 22 Jun 2005 19:02:37 -0000 *************** *** 49,55 **** typedef enum { START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD, ! EAT_CRNL } ParserState; typedef enum { --- 49,55 ---- typedef enum { START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD, ! EAT_CRNL, SKIP_RECORD, SKIPPED_RECORD } ParserState; typedef enum { *************** *** 79,84 **** --- 79,85 ---- int skipinitialspace; /* ignore spaces following delimiter? */ PyObject *lineterminator; /* string to write between records */ int quoting; /* style of quoting to write */ + char commentchar; /* starts comment lines in CSV file */ int strict; /* raise exception on bad CSV */ } DialectObj; *************** *** 273,278 **** --- 274,280 ---- { "skipinitialspace", T_INT, D_OFF(skipinitialspace), READONLY }, { "doublequote", T_INT, D_OFF(doublequote), READONLY }, { "strict", T_INT, D_OFF(strict), READONLY }, + { "commentchar", T_CHAR, D_OFF(commentchar), READONLY }, { NULL } }; *************** *** 301,306 **** --- 303,309 ---- "quoting", "skipinitialspace", "strict", + "commentchar", NULL }; *************** *** 318,326 **** PyObject *quoting = NULL; PyObject *skipinitialspace = NULL; PyObject *strict = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, ! "|OOOOOOOOO", dialect_kws, &dialect, &delimiter, &doublequote, --- 321,330 ---- PyObject *quoting = NULL; PyObject *skipinitialspace = NULL; PyObject *strict = NULL; + PyObject *commentchar = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, ! "|OOOOOOOOOO", dialect_kws, &dialect, &delimiter, &doublequote, *************** *** 329,335 **** "echar, "ing, &skipinitialspace, ! &strict)) return NULL; if (dialect != NULL) { --- 333,340 ---- "echar, "ing, &skipinitialspace, ! &strict, ! &commentchar)) return NULL; if (dialect != NULL) { *************** *** 349,355 **** quotechar == 0 && quoting == 0 && skipinitialspace == 0 && ! strict == 0) return dialect; } --- 354,361 ---- quotechar == 0 && quoting == 0 && skipinitialspace == 0 && ! strict == 0 && ! commentchar == 0) return dialect; } *************** *** 368,373 **** --- 374,380 ---- Py_XINCREF(quoting); Py_XINCREF(skipinitialspace); Py_XINCREF(strict); + Py_XINCREF(commentchar); if (dialect != NULL) { #define DIALECT_GETATTR(v, n) \ if (v == NULL) \ *************** *** 380,385 **** --- 387,393 ---- DIALECT_GETATTR(quoting, "quoting"); DIALECT_GETATTR(skipinitialspace, "skipinitialspace"); DIALECT_GETATTR(strict, "strict"); + DIALECT_GETATTR(commentchar, "commentchar"); PyErr_Clear(); } *************** *** 395,400 **** --- 403,409 ---- 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); + DIASET(_set_char, "commentchar", &self->commentchar, commentchar, 0); /* validate options */ if (dialect_check_quoting(self->quoting)) *************** *** 414,419 **** --- 423,432 ---- PyErr_SetString(PyExc_TypeError, "lineterminator must be set"); goto err; } + if (self->commentchar == ' ') { + PyErr_SetString(PyExc_TypeError, "commentchar cannot be a space"); + goto err; + } ret = (PyObject *)self; Py_INCREF(self); *************** *** 428,433 **** --- 441,447 ---- Py_XDECREF(quoting); Py_XDECREF(skipinitialspace); Py_XDECREF(strict); + Py_XDECREF(commentchar); return ret; } *************** *** 568,573 **** --- 582,590 ---- DialectObj *dialect = self->dialect; switch (self->state) { + case SKIPPED_RECORD: + /* fallthru */ + /* Needed because START_RECORD currently causes fields to be returned */ case START_RECORD: /* start of record */ if (c == '\0') *************** *** 577,582 **** --- 594,604 ---- self->state = EAT_CRNL; break; } + else if (c == dialect->commentchar) { + /* comment line - ignore */ + self->state = SKIP_RECORD; + break; + } /* normal character - handle as START_FIELD */ self->state = START_FIELD; /* fallthru */ *************** *** 728,733 **** --- 750,760 ---- } break; + case SKIP_RECORD: + if (c == '\0') + self->state = SKIPPED_RECORD; + break; + } return 0; } *************** *** 1447,1452 **** --- 1474,1480 ---- " skipinitialspace = False\n" " lineterminator = '\\r\\n'\n" " quoting = QUOTE_MINIMAL\n" + " commentchar = None\n" "\n" "SETTINGS:\n" "\n" *************** *** 1458,1463 **** --- 1486,1493 ---- " 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" + " * commentchar - specifices a one-character string which identifies\n" + " comment lines. It defaults to '' (i.e. no comment)." " * lineterminator - specifies the character sequence which should \n" " terminate rows.\n" " * quoting - controls when quotes should be generated by the writer.\n" Index: Lib/csv.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/csv.py,v retrieving revision 1.15 diff -c -c -r1.15 csv.py *** Lib/csv.py 12 Jan 2005 03:45:00 -0000 1.15 --- Lib/csv.py 22 Jun 2005 19:02:48 -0000 *************** *** 26,32 **** This must be subclassed (see csv.excel). Valid attributes are: delimiter, quotechar, escapechar, doublequote, skipinitialspace, ! lineterminator, quoting. """ _name = "" --- 26,32 ---- This must be subclassed (see csv.excel). Valid attributes are: delimiter, quotechar, escapechar, doublequote, skipinitialspace, ! lineterminator, quoting, commentchar. """ _name = "" *************** *** 39,44 **** --- 39,45 ---- skipinitialspace = None lineterminator = None quoting = None + commentchar = None def __init__(self): if self.__class__ != Dialect: *************** *** 60,65 **** --- 61,67 ---- skipinitialspace = False lineterminator = '\r\n' quoting = QUOTE_MINIMAL + commentchar = None register_dialect("excel", excel) class excel_tab(excel):