Skip to content

Commit 0bc6595

Browse files
[3.13] gh-103925: Fix csv.Sniffer for a quoted field ending a CRLF line (GH-103926) (GH-154330)
"$" does not match before "\r" even in the MULTILINE mode, so such a field was not found and the delimiter was guessed from character frequencies instead, which could give a letter. (cherry picked from commit 70f7c6c) Co-authored-by: Zhou Wei <lilaboc.cn@gmail.com>
1 parent b8d3151 commit 0bc6595

3 files changed

Lines changed: 13 additions & 4 deletions

File tree

Lib/csv.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,10 @@ def _guess_quote_and_delimiter(self, data, delimiters):
283283
"""
284284

285285
matches = []
286-
for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",
287-
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?",
288-
r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)', # ,".*?"
289-
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space)
286+
for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",
287+
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?",
288+
r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\r|\n)', # ,".*?"
289+
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\r|\n)'): # ".*?" (no delim, no space)
290290
regexp = re.compile(restr, re.DOTALL | re.MULTILINE)
291291
matches = regexp.findall(data)
292292
if matches:

Lib/test/test_csv.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,9 @@ class TestSniffer(unittest.TestCase):
13571357
ghi\0jkl
13581358
"""
13591359

1360+
sample19 = ('time,title\r\n'
1361+
'2020-10-01,"Pocket - Save news, videos, stories and more"\r\n')
1362+
13601363
def test_issue43625(self):
13611364
sniffer = csv.Sniffer()
13621365
self.assertTrue(sniffer.has_header(self.sample12))
@@ -1427,6 +1430,9 @@ def test_delimiters(self):
14271430
self.assertEqual(dialect.quotechar, "'")
14281431
dialect = sniffer.sniff(self.sample14)
14291432
self.assertEqual(dialect.delimiter, '\0')
1433+
dialect = sniffer.sniff(self.sample19)
1434+
self.assertEqual(dialect.delimiter, ',')
1435+
self.assertEqual(dialect.quotechar, '"')
14301436

14311437
def test_doublequote(self):
14321438
sniffer = csv.Sniffer()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :meth:`csv.Sniffer.sniff` for a sample with ``\r\n`` line endings in
2+
which a quoted field ends a line: a letter could be detected as the
3+
delimiter.

0 commit comments

Comments
 (0)