fix(csv): read the separator the file was written with - #2517
Open
Lukas (L4XB) wants to merge 1 commit into
Open
Lukas (L4XB) wants to merge 1 commit into
Lukas (L4XB) wants to merge 1 commit into
Conversation
A .csv file is not always comma separated. Excel writes the list separator of the machine's locale, which is a semicolon across most of Europe, and a tab-separated export is routinely saved as .csv. Parsing either one with a comma does not fail: it returns one column holding the whole row, separators included, so every column boundary in the file is lost. Detect the separator among comma, semicolon and tab by taking the one that gives the same column count on every row of a sample, keeping the comma when none of them does, so an ambiguous or ragged file is parsed exactly as before. A leading `sep=` line, which Excel writes and honours, sets the separator directly and is no longer emitted as a table row.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
CsvConverterparses every file withcsv.reader(...), which means a comma. A.csvfile is not always comma separated:Save as → CSVon a German, French, Spanish or Italian Windows producesName;Region;Units..csvextension.Parsing those with a comma does not fail. It returns one column holding the whole row, separators and all:
Every column boundary in the file is gone, and the markdown table claims the file has one column. Same for the tab case, where the raw tab ends up inside the cell.
How
,,;and\tby the one that yields the same column count on every row of a sample (the first 20 non-blank rows, capped at 64 KB). A separator the file was not written with either does not occur at all, or occurs by accident and then the rows do not line up — which is what keeps a comma inside a sentence, or a semicolon inside a quoted field, from being read as one.sep=line — which Excel writes and honours, and hides from the user — now sets the separator directly, and stops being emitted as a table row. It is read after the BOM is stripped, so a BOM-prefixed export works too.Test
packages/markitdown/tests/test_csv_delimiter.py— nine tests. The same table is written three times, once per separator, and must convert to the same markdown.maintests/test_csv_delimiter.pyThe five that pass on both sides are the guards that must not move: the comma case, a semicolon inside a quoted field, a single-column file whose values contain semicolons, a ragged comma file (the padding behaviour
test_csv_blank_runs.pypins), and an empty file.Full suite: 901 passed, 14 skipped, including
test_csv_blank_runs.pyandtest_csv_line_endings.pyunchanged.black(the pinned 23.7.0 from.pre-commit-config.yaml) reports both files unchanged.