Datagrunt 4.6.5: CSV Dialect Sniffing Synced with CPython's 2026 Fixes

October 30, 2026by Martin Graham

Datagrunt 4.6.5 is now available. It fixes CSV dialect sniffing for quoted fields that contain doubled quotes, and it changes the detected dialect for some files. Read What changes for you before upgrading if you depend on the sniffed quote character.


Why This Release

Datagrunt’s dialect sniffer is a port of CPython’s csv.Sniffer, running in the Rust core with a pure-Python reference implementation used for parity testing. CPython’s patch releases from July and August 2026 (3.10.22, 3.11.18, 3.13.18, 3.14.10) fixed three problems in csv.Sniffer:

  • gh-98820: a quoted field’s body now ends at the first quote that is not doubled. Before, the pattern could slide across the doubled quotes in a field like "say ""hi"" now", and the sniffer reported a space as the delimiter.
  • gh-109638: doubled quotes are looked for inside whole fields, and only once a delimiter has been found.
  • gh-103925: \r\n and \r line endings are normalised before sniffing.

The two regular-expression fixes also remove slow worst cases on adversarial input. Datagrunt 4.6.5 ports all three into both the Rust core and the Python reference, which now agree again on every supported Python version.


What Changes for You

The sniffer supplies quotechar, doublequote and skipinitialspace (via CSVComponents / CSVDialect). CSVComponents.delimiter comes from Datagrunt’s separate delimiter inference and does not change.

  • quotechar can change. When apostrophe-quoted values come first in a file, the detected quote character can now be ' instead of ", matching CPython. The DuckDB engine reads with this quote character, so check DuckDB-engine reads of such files after upgrading.
  • doublequote is now False for single-column quoted data and when no delimiter was found from quoted fields; it is now True when quoted fields also contain the delimiter.
  • skipinitialspace can flip either way for ; -style spaced files.
  • Some files no longer yield a sniffed dialect (for example note\n"a, ""b"""\n). Datagrunt then uses its defaults: " as the quote character, doublequote=False, skipinitialspace=False.

To see what Datagrunt detects for a file:

from datagrunt.core import CSVComponents

components = CSVComponents("sample.csv")
print(components.delimiter, components.quotechar, components.doublequote, components.skipinitialspace)

Also in This Release

  • License notice. The sniffer code is derived from CPython, so the distribution now includes THIRD_PARTY_NOTICES.txt with the Python Software Foundation License notice.
  • Internal: Datagrunt’s own test suite now builds its PDF test files with ReportLab. Nothing changes for users.

Upgrading

uv pip install --upgrade datagrunt