Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions sqlite_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,24 @@ class Format(enum.Enum):
with buffered:
return rows_from_file(buffered, format=Format.JSON)
else:
dialect = csv.Sniffer().sniff(
first_bytes.decode(encoding or "utf-8-sig", "ignore")
)
try:
dialect = csv.Sniffer().sniff(
first_bytes.decode(encoding or "utf-8-sig", "ignore")
)
except csv.Error:
# Single-column files have no delimiter to sniff (e.g. a bare
# "id\n1\n2\n" list). Fall back to the default CSV dialect so
# DictReader still loads them as a single column.
dialect = None
rows, _ = rows_from_file(
buffered, format=Format.CSV, dialect=dialect, encoding=encoding
)
# Make sure we return the format we detected
detected_format = Format.TSV if dialect.delimiter == "\t" else Format.CSV
detected_format = (
Format.TSV
if dialect is not None and dialect.delimiter == "\t"
else Format.CSV
)
return (
_extra_key_strategy(
cast(Iterable[dict[str | None, object]], rows),
Expand Down
15 changes: 15 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ def test_hash_record():
)


@pytest.mark.parametrize(
"content,expected",
(
(b"apple\nbanana\ncherry\n", [{"apple": "banana"}, {"apple": "cherry"}]),
(b"id\n1\n2\n", [{"id": "1"}, {"id": "2"}]),
),
)
def test_rows_from_file_detects_single_column_csv(content, expected):
# A single-column file has no delimiter for csv.Sniffer to detect; it
# used to raise csv.Error("Could not determine delimiter").
rows, format_ = utils.rows_from_file(io.BytesIO(content))
assert format_ == utils.Format.CSV
assert list(rows) == expected


def test_maximize_csv_field_size_limit():
# Reset to default in case other tests have changed it
csv.field_size_limit(utils.ORIGINAL_CSV_FIELD_SIZE_LIMIT)
Expand Down
Loading