[Python-checkins] python/dist/src/Modules _csv.c,1.30,1.31

andrewmcnamara at users.sourceforge.net andrewmcnamara at users.sourceforge.net
Wed Jan 12 08:44:44 CET 2005


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19456/Modules

Modified Files:
	_csv.c 
Log Message:
When using QUOTE_NONNUMERIC, we now test for "numericness" with
PyNumber_Check, rather than trying to convert to a float.  Reimplemented
writer - now raises exceptions when it sees a quotechar but neither
doublequote or escapechar are set. Doublequote results are now more
consistent (eg, single quote should generate """", rather than "",
which is ambiguous).


Index: _csv.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_csv.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- _csv.c	12 Jan 2005 03:45:00 -0000	1.30
+++ _csv.c	12 Jan 2005 07:44:41 -0000	1.31
@@ -944,81 +944,65 @@
 {
         DialectObj *dialect = self->dialect;
 	int i, rec_len;
+	char *lineterm;
+
+#define ADDCH(c) \
+	do {\
+		if (copy_phase) \
+			self->rec[rec_len] = c;\
+		rec_len++;\
+	} while(0)
+
+	lineterm = PyString_AsString(dialect->lineterminator);
+	if (lineterm == NULL)
+		return -1;
 
 	rec_len = self->rec_len;
 
-	/* If this is not the first field we need a field separator.
-	 */
-	if (self->num_fields > 0) {
-		if (copy_phase)
-			self->rec[rec_len] = dialect->delimiter;
-		rec_len++;
-	}
-	/* Handle preceding quote.
-	 */
-	switch (dialect->quoting) {
-	case QUOTE_ALL:
-		*quoted = 1;
-		if (copy_phase)
-			self->rec[rec_len] = dialect->quotechar;
-		rec_len++;
-		break;
-	case QUOTE_MINIMAL:
-	case QUOTE_NONNUMERIC:
-		/* We only know about quoted in the copy phase.
-		 */
-		if (copy_phase && *quoted) {
-			self->rec[rec_len] = dialect->quotechar;
-			rec_len++;
-		}
-		break;
-	case QUOTE_NONE:
-		break;
-	}
-	/* Copy/count field data.
-	 */
+	/* 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 */
 	for (i = 0;; i++) {
 		char c = field[i];
+		int want_escape = 0;
 
 		if (c == '\0')
 			break;
-		/* If in doublequote mode we escape quote chars with a
-		 * quote.
-		 */
-		if (dialect->quoting != QUOTE_NONE && 
-                    c == dialect->quotechar && dialect->doublequote) {
-			if (copy_phase)
-				self->rec[rec_len] = dialect->quotechar;
-			*quoted = 1;
-			rec_len++;
-		}
 
-		/* Some special characters need to be escaped.  If we have a
-		 * quote character switch to quoted field instead of escaping
-		 * individual characters.
-		 */
-		if (!*quoted
-		    && (c == dialect->delimiter || 
-                        c == dialect->escapechar || 
-                        c == '\n' || c == '\r')) {
-			if (dialect->quoting != QUOTE_NONE)
-				*quoted = 1;
-			else if (dialect->escapechar) {
-				if (copy_phase)
-					self->rec[rec_len] = dialect->escapechar;
-				rec_len++;
-			}
+		if (c == dialect->delimiter ||
+		    c == dialect->escapechar ||
+		    c == dialect->quotechar ||
+		    strchr(lineterm, c)) {
+			if (dialect->quoting == QUOTE_NONE)
+				want_escape = 1;
 			else {
-				PyErr_Format(error_obj, 
-                                             "delimiter must be quoted or escaped");
-				return -1;
+				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) {
+					PyErr_Format(error_obj, 
+						     "need to escape, but no escapechar set");
+					return -1;
+				}
+				ADDCH(dialect->escapechar);
 			}
 		}
 		/* Copy field character into record buffer.
 		 */
-		if (copy_phase)
-			self->rec[rec_len] = c;
-		rec_len++;
+		ADDCH(c);
 	}
 
 	/* If field is empty check if it needs to be quoted.
@@ -1033,20 +1017,14 @@
 			*quoted = 1;
 	}
 
-	/* Handle final quote character on field.
-	 */
 	if (*quoted) {
 		if (copy_phase)
-			self->rec[rec_len] = dialect->quotechar;
+			ADDCH(dialect->quotechar);
 		else
-			/* Didn't know about leading quote until we found it
-			 * necessary in field data - compensate for it now.
-			 */
-			rec_len++;
-		rec_len++;
+			rec_len += 2;
 	}
-
 	return rec_len;
+#undef ADDCH
 }
 
 static int
@@ -1146,18 +1124,16 @@
 		if (field == NULL)
 			return NULL;
 
-		quoted = 0;
-		if (dialect->quoting == QUOTE_NONNUMERIC) {
-			PyObject *num;
-
-			num = PyNumber_Float(field);
-			if (num == NULL) {
-				quoted = 1;
-				PyErr_Clear();
-			}
-			else {
-				Py_DECREF(num);
-			}
+		switch (dialect->quoting) {
+		case QUOTE_NONNUMERIC:
+			quoted = !PyNumber_Check(field);
+			break;
+		case QUOTE_ALL:
+			quoted = 1;
+			break;
+		default:
+			quoted = 0;
+			break;
 		}
 
 		if (PyString_Check(field)) {



More information about the Python-checkins mailing list