Summary
morpc.write_table() raises RuntimeError whenever format is not passed explicitly. It derives the format from the file extension as ".csv" — with the leading dot — but PANDAS_EXPORT_ARGS_OVERRIDE is keyed "csv", so the lookup never matches.
The auto-detection branch has therefore never worked for any format. Confirmed on main at v0.5.18.
Reproduction
import morpc, pandas as pd, tempfile, os
df = pd.DataFrame({"a": [1, 2]})
path = os.path.join(tempfile.mkdtemp(), "t.csv")
morpc.write_table(df, path, index=False) # RuntimeError
morpc.write_table(df, path, format="csv", index=False) # works
morpc.write_table | INFO | Format is unspecified. Will attempt to determine format based on file extension.
morpc.write_table | ERROR | This function does not currently support format .csv.
Add export arguments for this format in morpc.PANDAS_EXPORT_ARGS_OVERRIDE or use the
native pandas export functions.
RuntimeError
Note the error message itself shows the mismatch: format .csv against a dict keyed csv.
Cause
morpc/morpc.py line 3041:
format = os.path.splitext(path)[1] # -> ".csv", not "csv"
against the dict at line 11:
PANDAS_EXPORT_ARGS_OVERRIDE = {
"csv": {"lineterminator": "\r\n"},
"xlsx": None
}
The lookup at line 3046 raises KeyError, which is converted to RuntimeError. Even if the lookup were made tolerant, the dispatch at lines 3055 and 3057 compares format == "csv" / == "xlsx" and would fall through to the same error, so the dot has to be stripped at the source.
Fix
- format = os.path.splitext(path)[1]
+ format = os.path.splitext(path)[1].lstrip(".")
That fixes both the lookup and the dispatch.
Alternatively, use the EXTENSION_MAP idiom already established in morpc/frictionless/frictionless.py (lines 610-612), which is keyed by extension with the dot and maps to the bare format name. create_resource() gets this right for the same file — it logs Format not specified. Using format derived from data file extension: csv — so the two functions in the same package currently disagree about what "format" means.
Why this has gone unnoticed
Every MORPC standardize repository I checked passes format="csv" explicitly, so nothing in production hits the auto-detection path:
write_table(features, OUTPUT_PATH, format="csv", index=False)
write_table(facilities, FACILITIES_PATH, format="csv", index=False)
write_table(summaryOut, SUMMARY_PATH, format="csv", index=False)
The exception is morpc-repotemplate-standardize, whose summary-table cell calls morpc.write_table(summaryOut, SUMMARY_PATH, index=False) with no format. So every new repository scaffolded from the template fails at that cell until someone adds format="csv". repo_setup.md line 161 also tells authors to "Write CSVs with morpc.write_table()" without mentioning the argument.
Worth fixing the template as well as the function, or the next scaffolded repo hits it again.
Impact
Found while converting morpc-ohiodbhfacilities-standardize to GeoPackage releases; that repository was scaffolded from the template and inherited the argument-less call. It now passes format="csv" explicitly with a comment pointing at this behaviour.
Related: #174, also in code that resolves a format or driver and then fails to use it.
Summary
morpc.write_table()raisesRuntimeErrorwheneverformatis not passed explicitly. It derives the format from the file extension as".csv"— with the leading dot — butPANDAS_EXPORT_ARGS_OVERRIDEis keyed"csv", so the lookup never matches.The auto-detection branch has therefore never worked for any format. Confirmed on
mainatv0.5.18.Reproduction
Note the error message itself shows the mismatch:
format .csvagainst a dict keyedcsv.Cause
morpc/morpc.pyline 3041:against the dict at line 11:
The lookup at line 3046 raises
KeyError, which is converted toRuntimeError. Even if the lookup were made tolerant, the dispatch at lines 3055 and 3057 comparesformat == "csv"/== "xlsx"and would fall through to the same error, so the dot has to be stripped at the source.Fix
That fixes both the lookup and the dispatch.
Alternatively, use the
EXTENSION_MAPidiom already established inmorpc/frictionless/frictionless.py(lines 610-612), which is keyed by extension with the dot and maps to the bare format name.create_resource()gets this right for the same file — it logsFormat not specified. Using format derived from data file extension: csv— so the two functions in the same package currently disagree about what "format" means.Why this has gone unnoticed
Every MORPC standardize repository I checked passes
format="csv"explicitly, so nothing in production hits the auto-detection path:The exception is
morpc-repotemplate-standardize, whose summary-table cell callsmorpc.write_table(summaryOut, SUMMARY_PATH, index=False)with no format. So every new repository scaffolded from the template fails at that cell until someone addsformat="csv".repo_setup.mdline 161 also tells authors to "Write CSVs withmorpc.write_table()" without mentioning the argument.Worth fixing the template as well as the function, or the next scaffolded repo hits it again.
Impact
Found while converting
morpc-ohiodbhfacilities-standardizeto GeoPackage releases; that repository was scaffolded from the template and inherited the argument-less call. It now passesformat="csv"explicitly with a comment pointing at this behaviour.Related: #174, also in code that resolves a format or driver and then fails to use it.