From 37fee45ad7142657afc3117da2208c036187b246 Mon Sep 17 00:00:00 2001 From: Robert Leander Date: Tue, 30 Jun 2026 08:47:34 +0200 Subject: [PATCH 1/3] relocated ipf columns number warning one level up and added filename to the warning text --- imod/formats/ipf.py | 52 +++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/imod/formats/ipf.py b/imod/formats/ipf.py index 653142a0b..5ef7c5961 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,18 @@ 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," + + " first line of file:\n{f.name} \ncontains {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, + ) f.seek(position) sep = r"\s+" if delim_whitespace else "," @@ -166,7 +168,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," + + " first line of file:\n{f.name} \ncontains {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) sep = r"\s+" if delim_whitespace else "," # Normally, this ought to work: # metadata = pd.read_csv(f, header=None, nrows=ncol).values @@ -204,7 +218,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," + + " first datablock of file:\n{f.name} \ncontains {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, + ) + sep = r"\s+" if delim_whitespace else "," itype_kwargs = { From 73d77a9d73ba881ba03ce619ae037619decec2ca Mon Sep 17 00:00:00 2001 From: Robert Leander Date: Wed, 1 Jul 2026 16:13:58 +0200 Subject: [PATCH 2/3] added test_read_comma_wrong on the ipf read to check if the filename ends up in the log warning message --- imod/formats/ipf.py | 9 ++++---- imod/tests/test_formats/test_ipf.py | 32 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/imod/formats/ipf.py b/imod/formats/ipf.py index 5ef7c5961..071184c21 100644 --- a/imod/formats/ipf.py +++ b/imod/formats/ipf.py @@ -50,14 +50,15 @@ def _read_ipf(path, kwargs=None) -> Tuple[pd.DataFrame, int, str]: if not has_expected_cols: log_message = ( f"Inconsistent IPF: header states {ncol} columns," - + " first line of file:\n{f.name} \ncontains {len(line.split())} whitespace-delimited" - + " columns and {len(next(csv.reader([line])))} comma-delimited 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 "," @@ -180,7 +181,7 @@ def read_associated(path, kwargs={}): message=log_message, additional_depth=2, ) - warnings.warn(log_message) + 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 @@ -230,7 +231,7 @@ def read_associated(path, kwargs={}): 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..fae4e3010 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 deliberatie 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, ",") From 81c4d817ed11a95eb74d1c81c6986bab92a163e5 Mon Sep 17 00:00:00 2001 From: Robert Leander Date: Thu, 2 Jul 2026 11:41:48 +0200 Subject: [PATCH 3/3] review comment: forgot format f's --- imod/formats/ipf.py | 8 ++++---- imod/tests/test_formats/test_ipf.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imod/formats/ipf.py b/imod/formats/ipf.py index 071184c21..783d15333 100644 --- a/imod/formats/ipf.py +++ b/imod/formats/ipf.py @@ -173,8 +173,8 @@ def read_associated(path, kwargs={}): if not has_expected_cols: log_message = ( f"Inconsistent IPF: header states {ncol} columns," - + " first line of file:\n{f.name} \ncontains {len(line.split())} whitespace-delimited" - + " columns and {len(next(csv.reader([line])))} comma-delimited 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, @@ -223,8 +223,8 @@ def read_associated(path, kwargs={}): if not has_expected_cols: log_message = ( f"Inconsistent IPF: header states {ncol} columns," - + " first datablock of file:\n{f.name} \ncontains {len(line.split())} whitespace-delimited" - + " columns and {len(next(csv.reader([line])))} comma-delimited 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, diff --git a/imod/tests/test_formats/test_ipf.py b/imod/tests/test_formats/test_ipf.py index fae4e3010..37b089f92 100644 --- a/imod/tests/test_formats/test_ipf.py +++ b/imod/tests/test_formats/test_ipf.py @@ -121,7 +121,7 @@ def test_read__comma_wrong(write_basic_ipf, tmp_path, monkeypatch): path = "basic_comma.ipf" write_basic_ipf(path, ",") - # modify the ipf file to deliberatie create an error by adding a column + # 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"