diff --git a/imod/formats/ipf.py b/imod/formats/ipf.py index 653142a0b..783d15333 100644 --- a/imod/formats/ipf.py +++ b/imod/formats/ipf.py @@ -24,16 +24,7 @@ def _infer_delimwhitespace(line, ncol): delimiter_info = infer_line_delimiter_info(line, ncol) - - if not delimiter_info.has_expected_cols: - log_message = f"Inconsistent IPF: header states {ncol} columns, first line contains {len(line.split())} whitespace-delimited columns and {len(next(csv.reader([line])))} comma-delimited columns." - imod.logging.logger.log( - loglevel=LogLevel.WARNING, - message=log_message, - additional_depth=2, - ) - warnings.warn(log_message) - return delimiter_info.has_whitespace + return delimiter_info.has_whitespace, delimiter_info.has_expected_cols def _read_ipf(path, kwargs=None) -> Tuple[pd.DataFrame, int, str]: @@ -55,7 +46,19 @@ def _read_ipf(path, kwargs=None) -> Tuple[pd.DataFrame, int, str]: position = f.tell() line = f.readline() - delim_whitespace = _infer_delimwhitespace(line, ncol) + delim_whitespace, has_expected_cols = _infer_delimwhitespace(line, ncol) + if not has_expected_cols: + log_message = ( + f"Inconsistent IPF: header states {ncol} columns," + + f" first line of file [{f.name}] contains {len(line.split())} whitespace-delimited" + + f" columns and {len(next(csv.reader([line])))} comma-delimited columns." + ) + imod.logging.logger.log( + loglevel=LogLevel.WARNING, + message=log_message, + additional_depth=2, + ) + warnings.warn(log_message) f.seek(position) sep = r"\s+" if delim_whitespace else "," @@ -166,7 +169,19 @@ def read_associated(path, kwargs={}): # this is a workaround for a pandas bug, probable related issue: # https://github.com/pandas-dev/pandas/issues/19827#issuecomment-398649163 lines = [f.readline() for _ in range(ncol)] - delim_whitespace = _infer_delimwhitespace(lines[0], 2) + delim_whitespace, has_expected_cols = _infer_delimwhitespace(lines[0], 2) + if not has_expected_cols: + log_message = ( + f"Inconsistent IPF: header states {ncol} columns," + + f" first line of file:\n{f.name} \ncontains {len(line.split())} whitespace-delimited" + + f" columns and {len(next(csv.reader([line])))} comma-delimited columns." + ) + imod.logging.logger.log( + loglevel=LogLevel.WARNING, + message=log_message, + additional_depth=2, + ) + warnings.warn(log_message) sep = r"\s+" if delim_whitespace else "," # Normally, this ought to work: # metadata = pd.read_csv(f, header=None, nrows=ncol).values @@ -204,7 +219,19 @@ def read_associated(path, kwargs={}): position = f.tell() line = f.readline() f.seek(position) - delim_whitespace = _infer_delimwhitespace(line, ncol) + delim_whitespace, has_expected_cols = _infer_delimwhitespace(line, ncol) + if not has_expected_cols: + log_message = ( + f"Inconsistent IPF: header states {ncol} columns," + + f" first datablock of file:\n{f.name} \ncontains {len(line.split())} whitespace-delimited" + + f" columns and {len(next(csv.reader([line])))} comma-delimited columns." + ) + imod.logging.logger.log( + loglevel=LogLevel.WARNING, + message=log_message, + additional_depth=2, + ) + warnings.warn(log_message) sep = r"\s+" if delim_whitespace else "," itype_kwargs = { diff --git a/imod/tests/test_formats/test_ipf.py b/imod/tests/test_formats/test_ipf.py index 450282c99..37b089f92 100644 --- a/imod/tests/test_formats/test_ipf.py +++ b/imod/tests/test_formats/test_ipf.py @@ -2,7 +2,10 @@ import pandas as pd import pytest +import imod.logging from imod import ipf +from imod.logging.config import LoggerType +from imod.logging.loglevel import LogLevel from imod.testing import assert_frame_equal @@ -106,6 +109,35 @@ def test_read_associated__itype1implicit(tmp_path): assert df.shape == (2, 2) +def test_read__comma_wrong(write_basic_ipf, tmp_path, monkeypatch): + # change working directory to tmp_path to ensure that the log file is created there + monkeypatch.chdir(tmp_path) + imod.logging.configure( + LoggerType.PYTHON, + LogLevel.WARNING, + add_default_stream_handler=False, + add_default_file_handler=True, + ) + path = "basic_comma.ipf" + write_basic_ipf(path, ",") + + # modify the ipf file to deliberately create an error by adding a column + with open(path, "r") as f: + content = f.readlines() + content[1] = "5\n" + content.insert(6, "Provincie\n") + with open(path, "w") as f: + f.writelines(content) + + # read the ipf file, which should trigger a warning due to the mismatch in number of columns + ipf.read(path) + + # check if the raised warning contains at least the file name of interest + with open("imod-python.log", "r") as ff: + # assert "["+path+"]" in ff.read() + assert f"[{path}]" in ff.read() + + def test_read__comma(write_basic_ipf, tmp_path): path = tmp_path / "basic_comma.ipf" write_basic_ipf(path, ",")