From 2001900b0c02a397d8cf1d776a7cc7fcb2a463e3 Mon Sep 17 00:00:00 2001 From: Licht Takeuchi Date: Tue, 12 Dec 2017 18:57:06 +0900 Subject: [PATCH] bpo-32255: Always quote a single empty field when write into a CSV file. (#4769) This allows to distinguish an empty row from a row consisting of a single empty field. --- Lib/test/test_csv.py | 21 ++++++++++++++++++- Misc/ACKS | 1 + .../2017-12-12-07-29-06.bpo-32255.2bfNmM.rst | 3 +++ Modules/_csv.c | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 03ab1840dd0..fe248019a0f 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -207,10 +207,29 @@ class Test_Csv(unittest.TestCase): with TemporaryFile("w+", newline='') as fileobj: writer = csv.writer(fileobj) self.assertRaises(TypeError, writer.writerows, None) - writer.writerows([['a','b'],['c','d']]) + writer.writerows([['a', 'b'], ['c', 'd']]) fileobj.seek(0) self.assertEqual(fileobj.read(), "a,b\r\nc,d\r\n") + def test_writerows_with_none(self): + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a', None], [None, 'd']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), "a,\r\n,d\r\n") + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([[None], ['a']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), '""\r\na\r\n') + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a'], [None]]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), 'a\r\n""\r\n') + @support.cpython_only def test_writerows_legacy_strings(self): import _testcapi diff --git a/Misc/ACKS b/Misc/ACKS index 54d8d62b633..8303ce80050 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1554,6 +1554,7 @@ Joel Taddei Arfrever Frehtes Taifersar Arahesis Hideaki Takahashi Takase Arihiro +Licht Takeuchi Indra Talip Neil Tallim Geoff Talvola diff --git a/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst new file mode 100644 index 00000000000..dafee67bdd0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst @@ -0,0 +1,3 @@ +A single empty field is now always quoted when written into a CSV file. +This allows to distinguish an empty row from a row consisting of a single empty field. +Patch by Licht Takeuchi. diff --git a/Modules/_csv.c b/Modules/_csv.c index 5314ef6edc4..e616151bae6 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1238,7 +1238,7 @@ csv_writerow(WriterObj *self, PyObject *seq) if (PyErr_Occurred()) return NULL; - if (self->num_fields > 0 && self->rec_size == 0) { + if (self->num_fields > 0 && self->rec_len == 0) { if (dialect->quoting == QUOTE_NONE) { PyErr_Format(_csvstate_global->error_obj, "single empty field record must be quoted");