Skip to content

Declare dbf, not csv, as the DBF format's file extension - #677

Open
MohammedAlkindi wants to merge 1 commit into
jazzband:masterfrom
MohammedAlkindi:fix/dbf-format-extension
Open

Declare dbf, not csv, as the DBF format's file extension#677
MohammedAlkindi wants to merge 1 commit into
jazzband:masterfrom
MohammedAlkindi:fix/dbf-format-extension

Conversation

@MohammedAlkindi

Copy link
Copy Markdown

DBFFormat.extensions is ('csv',). It was copied from CSVFormat in f1046cd when the formats became classes and never corrected. Every other format declares its own, so _json.py has ('json', 'jsn') and _xlsx.py has ('xlsx',).

Nothing inside tablib reads .extensions, which is why no test caught it. Downstream does read it. django-import-export's TablibFormat.get_extension() returns self.get_format().extensions[0], and get_export_filename() interpolates that into the filename the Django admin Export button serves. With django-import-export 4.4.1 and Django 6.1 a DBF export downloads as Invoice-2026-08-17.csv while its first bytes are \x03~\x08\x11 and tablib.detect_format correctly reports dbf. After the change it is Invoice-2026-08-17.dbf.

The test goes in the existing DBFTests class beside test_dbf_format_detect. On master it fails with Tuples differ: ('dbf',) != ('csv',).

Full suite on Python 3.13, 181 passed before and 182 after. Two tests fail identically either side and neither is touched here: test_auto_format_detect, which needs a pandas DLL my machine blocks, and test_getDate_datetime_timestamp, a timezone failure that is #675.

DBFFormat.extensions has read ('csv',) since the class-based format
refactor in f1046cd, where it was copy-pasted from CSVFormat and never
corrected. Nothing inside tablib reads .extensions, so the test suite
never noticed, but the attribute is public format metadata that
downstream consumers depend on.

django-import-export is the concrete case: TablibFormat.get_extension()
returns self.get_format().extensions[0], and get_export_filename()
interpolates that into the filename the Django admin Export button
serves. Measured against django-import-export 4.4.1 on Django 6.1, a
DBF export downloaded as Invoice-2026-08-17.csv even though its leading
bytes were a DBF header and tablib.detect_format correctly reported
dbf. With this change the same export is named Invoice-2026-08-17.dbf.

Adds a regression test to DBFTests. It is the first test in the suite
to assert on a format's extensions attribute, so the mismatch cannot
silently return.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant