fix: decode CSV delimiter-sniff sample as a single stream

2S
2mo ago
+42-4

Fixes #4443

Summary

partition_csv() crashed with UnicodeDecodeError: truncated data on UTF-16-LE files even when the correct encoding was passed, because _CsvPartitioningContext.delimiter decoded its sniff sample line-by-line: readlines() splits raw bytes on 0x0A, which lands mid-code-unit in UTF-16, and only the first fragment carries the BOM. UTF-16-BE didn't raise but silently fed the sniffer mojibake for every line after the first.

Fix

Keep the whole-line read semantics from #2998, but join the line fragments back into one byte stream and decode once with codecs.getincrementaldecoder(encoding)(...).decode(sample, final=False) — a character split at the read boundary is buffered instead of raising. Wrong-encoding inputs (e.g. latin-1 bytes decoded as utf-8) still raise exactly as before.

Testing

test_partition_csv_with_utf_16_le_encoding (end-to-end) and and_it_auto_detects_the_delimiter_for_a_UTF_16_encoded_CSV_file — both fail with the exact UnicodeDecodeError without the fix and pass with it. Full test_csv.py: 36 passed (includes the #2643 long-line regression, semicolon, single-column, and BE-utf-16 cases); test_tsv.py 15 passed; test_text.py 50 passed. ruff check + ruff format --check clean on touched files. CHANGELOG entry and version bump 0.26.3 → 0.26.4 included per repo convention.

Disclosure: prepared with AI assistance (Claude Code); I reviewed the change and take responsibility for it.