From 7f2053eff3ec1ee9084a3a550ae363a804368322 Mon Sep 17 00:00:00 2001 From: Andrew McNamara Date: Wed, 12 Jan 2005 11:17:16 +0000 Subject: Add counting of source iterator lines to the reader object - handy for user error messages (otherwise difficult to do without instrumenting the source). --- Lib/test/test_csv.py | 14 +++++++++++++- Misc/NEWS | 4 ++++ Modules/_csv.c | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index d458332..21bd8d7 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -242,7 +242,7 @@ class Test_Csv(unittest.TestCase): self._read_test(['1,",3,",5'], [['1', '"', '3', '"', '5']], quoting=csv.QUOTE_NONE, escapechar='\\') # will this fail where locale uses comma for decimals? - self._read_test([',3,"5",7.3'], [['', 3, '5', 7.3]], + self._read_test([',3,"5",7.3, 9'], [['', 3, '5', 7.3, 9]], quoting=csv.QUOTE_NONNUMERIC) self.assertRaises(ValueError, self._read_test, ['abc,3'], [[]], @@ -267,6 +267,18 @@ class Test_Csv(unittest.TestCase): finally: csv.field_size_limit(limit) + def test_read_linenum(self): + r = csv.reader(['line,1', 'line,2', 'line,3']) + self.assertEqual(r.line_num, 0) + r.next() + self.assertEqual(r.line_num, 1) + r.next() + self.assertEqual(r.line_num, 2) + r.next() + self.assertEqual(r.line_num, 3) + self.assertRaises(StopIteration, r.next) + self.assertEqual(r.line_num, 3) + class TestDialectRegistry(unittest.TestCase): def test_registry_badargs(self): self.assertRaises(TypeError, csv.list_dialects, None) diff --git a/Misc/NEWS b/Misc/NEWS index 828063a..26edc89 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,10 @@ Library + A new module method csv.field_size_limit() has been added that sets the parser field size limit (returning the former limit). The initial limit is 128kB. + + A line_num attribute has been added to the reader object, which tracks + the number of lines read from the source iterator. This is not + the same as the number of records returned, as records can span + multiple lines. + reader and writer objects were not being registered with the cyclic-GC. This has been fixed. diff --git a/Modules/_csv.c b/Modules/_csv.c index 6941714..ce4c738 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -98,6 +98,7 @@ typedef struct { int field_len; /* length of current field */ int had_parse_error; /* did we have a parse error? */ int numeric_field; /* treat field as numeric */ + unsigned long line_num; /* Source-file line number */ } ReaderObj; staticforward PyTypeObject Reader_Type; @@ -734,6 +735,7 @@ parse_process_char(ReaderObj *self, char c) static struct PyMemberDef Reader_memberlist[] = { { "dialect", T_OBJECT, R_OFF(dialect), RO }, + { "line_num", T_ULONG, R_OFF(line_num), RO }, { NULL } }; @@ -753,6 +755,7 @@ Reader_iternext(ReaderObj *self) "newline inside string"); return NULL; } + ++self->line_num; if (self->had_parse_error) if (parse_reset(self) < 0) { @@ -924,6 +927,7 @@ csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) self->input_iter = NULL; self->field = NULL; self->field_size = 0; + self->line_num = 0; if (parse_reset(self) < 0) { Py_DECREF(self); -- cgit v0.12