Skip to content

Commit

Permalink
559: Moved the parsing of Fortran scientifc notation for doubles to c…
Browse files Browse the repository at this point in the history
…ustom validator in base class
  • Loading branch information
tim-vd-aardweg committed Apr 18, 2024
1 parent 41ac1f1 commit 7180eff
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 20 deletions.
20 changes: 20 additions & 0 deletions hydrolib/core/dflowfm/ini/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from re import compile
from abc import ABC
from enum import Enum
from math import isnan
Expand Down Expand Up @@ -46,6 +47,7 @@ class INIBasedModel(BaseModel, ABC):

_header: str
_file_path_style_converter = FilePathStyleConverter()
_scientific_notation_regex = compile(r"([\d.]+)([dD])([+-]?\d{1,3})") # matches a float: 1d9, 1D-3, 1.D+4, etc.

class Config:
extra = Extra.ignore
Expand Down Expand Up @@ -123,6 +125,24 @@ def comments_matches_has_comments(cls, v):
v = None
return v

@validator("*", pre=True, allow_reuse=True)
def replace_fortran_scientific_notation_for_floats(cls, value, field):
if field.type_ != float:
return value

return cls._replace_fortran_scientific_notation(value)

@classmethod
def _replace_fortran_scientific_notation(cls, value):
if isinstance(value, str):
return cls._scientific_notation_regex.sub(r"\1e\3", value)
if isinstance(value, list):
for i, v in enumerate(value):
if isinstance(v, str):
value[i] = cls._scientific_notation_regex.sub(r"\1e\3", v)

return value

@classmethod
def validate(cls: Type["INIBasedModel"], value: Any) -> "INIBasedModel":
if isinstance(value, Section):
Expand Down
20 changes: 0 additions & 20 deletions hydrolib/core/dflowfm/ini/parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
from enum import IntEnum
from pathlib import Path
from typing import Callable, Dict, List, Optional, Tuple, Union
Expand Down Expand Up @@ -372,27 +371,8 @@ def parse(cls, filepath: Path, config: ParserConfig = None) -> Document:
config = ParserConfig()
parser = cls(config)

progline = re.compile(
r"^([^#]*=\s*)([^#]*)(#.*)?"
) # matches whole line: "Field = Value Maybe more # optional comment"
progfloat = re.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)

parser.feed_line(line)

return parser.finalize()

0 comments on commit 7180eff

Please sign in to comment.