Skip to content
Merged
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
53 changes: 40 additions & 13 deletions imod/formats/ipf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand All @@ -55,7 +46,19 @@

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."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
+ f" columns and {len(next(csv.reader([line])))} comma-delimited columns."
+ f" columns and line {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 ","

Expand Down Expand Up @@ -125,7 +128,7 @@
return df


def read_associated(path, kwargs={}):

Check failure on line 131 in imod/formats/ipf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=Deltares_imod-python&issues=AZ8eDEAbIxWsyRpgdyMI&open=AZ8eDEAbIxWsyRpgdyMI&pullRequest=1876
r"""
Read an IPF associated file (TXT).

Expand Down Expand Up @@ -166,7 +169,19 @@
# 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
Expand Down Expand Up @@ -204,7 +219,19 @@
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 = {
Expand Down
32 changes: 32 additions & 0 deletions imod/tests/test_formats/test_ipf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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, ",")
Expand Down
Loading