Read a single-column CSV file as one column when detecting the format

rows_from_file() sniffed the CSV dialect with no delimiters= list, so
csv.Sniffer considered every character. A single-column file then either
had no consistent candidate (csv.Error: Could not determine delimiter) or
was split on a letter that repeats on each line: a column of URLs came out
as {"ur": "https://examp", "": "e.com/a"}.

Format detection now sniffs for a comma, a semicolon, a tab or a pipe,
and reads a file with none of them as plain CSV.

Closes #907
This commit is contained in:
L4XB 2026-10-17 15:38:54 +02:00
commit bb93d57055
No known key found for this signature in database
3 changed files with 45 additions and 1 deletions

View file

@ -11,6 +11,7 @@ from sqlite_utils.utils import Format, RowError, rows_from_file
"input,expected_format",
(
(b"id,name\n1,Cleo", Format.CSV),
(b"id;name\n1;Cleo", Format.CSV),
(b"id\tname\n1\tCleo", Format.TSV),
(b'[{"id": "1", "name": "Cleo"}]', Format.JSON),
),
@ -22,6 +23,24 @@ def test_rows_from_file_detect_format(input, expected_format):
assert rows_list == [{"id": "1", "name": "Cleo"}]
@pytest.mark.parametrize(
"input,expected",
(
# csv.Sniffer could not determine a delimiter for this one
(b"name\nAnn\nBob\n", [{"name": "Ann"}, {"name": "Bob"}]),
# and took "l", which every line holds twice, for this one
(
b"url\nhttps://example.com/a\nhttps://example.org/b\n",
[{"url": "https://example.com/a"}, {"url": "https://example.org/b"}],
),
),
)
def test_rows_from_file_detect_format_single_column(input, expected):
rows, format = rows_from_file(BytesIO(input))
assert format == Format.CSV
assert list(rows) == expected
@pytest.mark.parametrize("input", (b"", b" \n\t"))
def test_rows_from_file_empty_input(input):
rows, format = rows_from_file(BytesIO(input))