Skip to content

Commit 6ce23d2

Browse files
Match the body of a quoted field without possessive quantifiers
They were added in 3.11. An unrolled loop is unambiguous at every position, so it does not backtrack either. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 83ac69c commit 6ce23d2

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

Lib/csv.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,14 @@ def _guess_quote_and_delimiter(self, data, delimiters):
269269
doublequote = False
270270
if delim:
271271
dq_regexp = re.compile(
272-
r"(?:(?<=%(delim)s)|^)%(space)s%(quote)s" # ,"
273-
r"((?:%(quote)s%(quote)s|[^%(quote)s]++)*+)" # the body
274-
r"%(quote)s(?:%(delim)s|$)" # ",
272+
r"(?:(?<=%(delim)s)|^)%(space)s%(quote)s" # ,"
273+
# The body, as an unrolled loop: it is unambiguous,
274+
# so it does not backtrack.
275+
r"([^%(quote)s]*(?:%(quote)s%(quote)s[^%(quote)s]*)*)"
276+
r"%(quote)s(?:%(delim)s|$)" # ",
275277
% {'delim': re.escape(delim), 'quote': quotechar,
276278
# Skipping spaces after a space rescans them.
277-
'space': ' *+' if delim != ' ' else ''},
279+
'space': ' *' if delim != ' ' else ''},
278280
re.MULTILINE)
279281
dquotechar = quotechar * 2
280282
doublequote = any(dquotechar in m[1]

0 commit comments

Comments
 (0)