summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Ezeh <sam.z.ezeh@gmail.com>2022-08-25 10:13:24 (GMT)
committerGitHub <noreply@github.com>2022-08-25 10:13:24 (GMT)
commitcd492d43a2980faf0ef4a3f99c665023a506414c (patch)
treec5758ce600d818dfdad9b1cbacb5b62aa3adc7a1
parentc09fa7542c6d9b724e423b14c6fb5f4338eabd12 (diff)
downloadcpython-cd492d43a2980faf0ef4a3f99c665023a506414c.zip
cpython-cd492d43a2980faf0ef4a3f99c665023a506414c.tar.gz
cpython-cd492d43a2980faf0ef4a3f99c665023a506414c.tar.bz2
gh-76728: Coerce DictReader and DictWriter fieldnames argument to a list (GH-32225)
-rw-r--r--Doc/library/csv.rst4
-rw-r--r--Lib/csv.py4
-rw-r--r--Lib/test/test_csv.py28
-rw-r--r--Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst1
4 files changed, 37 insertions, 0 deletions
diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst
index 9dec724..0cab95e 100644
--- a/Doc/library/csv.rst
+++ b/Doc/library/csv.rst
@@ -167,6 +167,8 @@ The :mod:`csv` module defines the following classes:
All other optional or keyword arguments are passed to the underlying
:class:`reader` instance.
+ If the argument passed to *fieldnames* is an iterator, it will be coerced to a :class:`list`.
+
.. versionchanged:: 3.6
Returned rows are now of type :class:`OrderedDict`.
@@ -209,6 +211,8 @@ The :mod:`csv` module defines the following classes:
Note that unlike the :class:`DictReader` class, the *fieldnames* parameter
of the :class:`DictWriter` class is not optional.
+ If the argument passed to *fieldnames* is an iterator, it will be coerced to a :class:`list`.
+
A short usage example::
import csv
diff --git a/Lib/csv.py b/Lib/csv.py
index bfc850e..0de5656 100644
--- a/Lib/csv.py
+++ b/Lib/csv.py
@@ -81,6 +81,8 @@ register_dialect("unix", unix_dialect)
class DictReader:
def __init__(self, f, fieldnames=None, restkey=None, restval=None,
dialect="excel", *args, **kwds):
+ if fieldnames is not None and iter(fieldnames) is fieldnames:
+ fieldnames = list(fieldnames)
self._fieldnames = fieldnames # list of keys for the dict
self.restkey = restkey # key to catch long rows
self.restval = restval # default value for short rows
@@ -133,6 +135,8 @@ class DictReader:
class DictWriter:
def __init__(self, f, fieldnames, restval="", extrasaction="raise",
dialect="excel", *args, **kwds):
+ if fieldnames is not None and iter(fieldnames) is fieldnames:
+ fieldnames = list(fieldnames)
self.fieldnames = fieldnames # list of keys for the dict
self.restval = restval # for writing short dicts
if extrasaction.lower() not in ("raise", "ignore"):
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index 95a19dd..51ca1f2 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -736,6 +736,34 @@ class TestDictFields(unittest.TestCase):
csv.DictWriter.writerow(writer, dictrow)
self.assertEqual(fileobj.getvalue(), "1,2\r\n")
+ def test_dict_reader_fieldnames_accepts_iter(self):
+ fieldnames = ["a", "b", "c"]
+ f = StringIO()
+ reader = csv.DictReader(f, iter(fieldnames))
+ self.assertEqual(reader.fieldnames, fieldnames)
+
+ def test_dict_reader_fieldnames_accepts_list(self):
+ fieldnames = ["a", "b", "c"]
+ f = StringIO()
+ reader = csv.DictReader(f, fieldnames)
+ self.assertEqual(reader.fieldnames, fieldnames)
+
+ def test_dict_writer_fieldnames_rejects_iter(self):
+ fieldnames = ["a", "b", "c"]
+ f = StringIO()
+ writer = csv.DictWriter(f, iter(fieldnames))
+ self.assertEqual(writer.fieldnames, fieldnames)
+
+ def test_dict_writer_fieldnames_accepts_list(self):
+ fieldnames = ["a", "b", "c"]
+ f = StringIO()
+ writer = csv.DictWriter(f, fieldnames)
+ self.assertEqual(writer.fieldnames, fieldnames)
+
+ def test_dict_reader_fieldnames_is_optional(self):
+ f = StringIO()
+ reader = csv.DictReader(f, fieldnames=None)
+
def test_read_dict_fields(self):
with TemporaryFile("w+", encoding="utf-8") as fileobj:
fileobj.write("1,2,abc\r\n")
diff --git a/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst b/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst
new file mode 100644
index 0000000..4599b73
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst
@@ -0,0 +1 @@
+The constructors for :class:`~csv.DictWriter` and :class:`~csv.DictReader` now coerce the ``fieldnames`` argument to a :class:`list` if it is an iterator.