Skip to content

Commit

Permalink
bug: Add regex for non scientific keys, move replacing scientific not…
Browse files Browse the repository at this point in the history
…ation to seperate method, add test case (#559)
  • Loading branch information
MRVermeulenDeltares committed Apr 17, 2024
1 parent 41ac1f1 commit e851e45
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
40 changes: 26 additions & 14 deletions hydrolib/core/dflowfm/ini/parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import re
from re import Pattern, compile
from enum import IntEnum
from pathlib import Path
from typing import Callable, Dict, List, Optional, Tuple, Union
Expand Down Expand Up @@ -371,28 +371,40 @@ def parse(cls, filepath: Path, config: ParserConfig = None) -> Document:
if not config:
config = ParserConfig()
parser = cls(config)

progNoScientificNotationkey = compile(
r'\b(?:id|name)\b'
) # matches for non scientific notation keys, e.g. id, name, nodeId, ManholeId.

progline = re.compile(
progline = compile(
r"^([^#]*=\s*)([^#]*)(#.*)?"
) # matches whole line: "Field = Value Maybe more # optional comment"
progfloat = re.compile(
progfloat = compile(
r"([\d.]+)([dD])([+\-]?\d{1,3})"
) # matches a float value: 1d9, 1D-3, 1.D+4, etc.

with filepath.open(encoding="utf8") as f:
for line in f:
# Replace Fortran scientific notation for doubles
# Match number d/D +/- number (e.g. 1d-05 or 1.23D+01 or 1.d-4)
match = progline.match(line)
if match: # Only process value
line = (
match.group(1)
+ progfloat.sub(r"\1e\3", match.group(2))
+ str(match.group(3) or "")
)
else: # Process full line
line = progfloat.sub(r"\1e\3", line)

match = progNoScientificNotationkey.search(line)
if not match:
line = cls._replace_fortran_scientific_notation_for_doubles(progline, progfloat, line)

parser.feed_line(line)

return parser.finalize()

@classmethod
def _replace_fortran_scientific_notation_for_doubles(cls, progline : Pattern[str], progfloat : Pattern[str], line : str):
# Replace Fortran scientific notation for doubles
# Match number d/D +/- number (e.g. 1d-05 or 1.23D+01 or 1.d-4)
match = progline.match(line)
if match: # Only process value
line = (
match.group(1)
+ progfloat.sub(r"\1e\3", match.group(2))
+ str(match.group(3) or "")
)
else: # Process full line
line = progfloat.sub(r"\1e\3", line)
return line
24 changes: 24 additions & 0 deletions tests/dflowfm/ini/test_ini.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import inspect
from itertools import chain
from typing import Iterable, List, Optional, Sequence, Tuple, Union
from unittest.mock import Mock

import pytest
from pydantic.v1 import ValidationError
Expand Down Expand Up @@ -1802,3 +1803,26 @@ def test_serialize_deserialize_should_give_the_same_result():
result = parser.finalize()

assert result == document

def test_parser_given_id_and_name_with_scientific_looking_notations_does_not_parse_as_scientific_notation(tmp_path):

file_data = """
[StorageNode]
id = 0D05252
name = 0D05252
"""

temporary_file_path_node_file = tmp_path / "nodeFile.ini"
temporary_file_path_node_file.write_text(file_data)

parser = Parser(Mock(spec=ParserConfig))
parse_data = parser.parse(temporary_file_path_node_file)

id = parse_data.sections[0].content[0]
name = parse_data.sections[0].content[1]

assert id.key == "id"
assert id.value == "0D05252"

assert name.key == "name"
assert name.value == "0D05252"

0 comments on commit e851e45

Please sign in to comment.