Skip to content

Commit

Permalink
Merge branch 'bug/559_Incorrect-parsing-of-string-starting-with-0D' of
Browse files Browse the repository at this point in the history
…https://github.com/Deltares/HYDROLIB-core into bug/559_Incorrect-parsing-of-string-starting-with-0D
  • Loading branch information
tim-vd-aardweg committed Apr 18, 2024
2 parents 9086267 + 3a52164 commit 395252a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 32 deletions.
6 changes: 4 additions & 2 deletions hydrolib/core/dflowfm/ini/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import logging
from re import compile
from abc import ABC
from enum import Enum
from math import isnan
from re import compile
from typing import Any, Callable, List, Literal, Optional, Set, Type, Union

from pydantic.v1 import Extra, Field, root_validator
Expand Down Expand Up @@ -47,7 +47,9 @@ 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.
_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
96 changes: 66 additions & 30 deletions tests/dflowfm/ini/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pydantic.v1.error_wrappers import ValidationError

from hydrolib.core.dflowfm.ini.models import DataBlockINIBasedModel, INIBasedModel

from ...utils import error_occurs_only_once


Expand Down Expand Up @@ -52,62 +53,97 @@ class INIBasedModelTest(INIBasedModel):
_random_list_of_floats: List[float] = [12.34, 56.78]

@pytest.mark.parametrize("string_value", ["1d0", "1d-2", "1d+2", "1.d+2", "-1.d-2"])
def test_scientific_notation_for_string_field_is_parsed_as_string(self, string_value: str):
def test_scientific_notation_for_string_field_is_parsed_as_string(
self, string_value: str
):

test_model = self.INIBasedModelTest(id=string_value, float_value=self._random_float,
float_values=self._random_list_of_floats)
test_model = self.INIBasedModelTest(
id=string_value,
float_value=self._random_float,
float_values=self._random_list_of_floats,
)

assert test_model.id == string_value
assert test_model.float_value == pytest.approx(self._random_float)
assert test_model.float_values == pytest.approx(self._random_list_of_floats)

@pytest.mark.parametrize("float_as_string, expected_value", [
("1d0", 1e0),
("1d-2", 1e-2),
("1d+2", 1e+2),
("1.d+2", 1.e+2),
("-1.d-2", -1.e-2)]
)
def test_scientific_notation_for_float_field_is_parsed_as_float(self, float_as_string: str, expected_value: float):
test_model = self.INIBasedModelTest(id=self._random_string, float_value=float_as_string,
float_values=self._random_list_of_floats)
@pytest.mark.parametrize(
"float_as_string, expected_value",
[
("1d0", 1e0),
("1d-2", 1e-2),
("1d+2", 1e2),
("1.d+2", 1.0e2),
("-1.d-2", -1.0e-2),
],
)
def test_scientific_notation_for_float_field_is_parsed_as_float(
self, float_as_string: str, expected_value: float
):
test_model = self.INIBasedModelTest(
id=self._random_string,
float_value=float_as_string,
float_values=self._random_list_of_floats,
)

assert test_model.id == self._random_string
assert test_model.float_value == pytest.approx(expected_value)
assert test_model.float_values == pytest.approx(self._random_list_of_floats)

@pytest.mark.parametrize("floats_as_strings, expected_values", [
(["1d0", "1d-2"], [1e0, 1e-2]),
(["1d+2", "1.d+2", "-1.d-2"], [1e+2, 1.e+2, -1.e-2]),
])
def test_scientific_notation_for_list_of_float_field_is_parsed_as_list_of_floats(self, floats_as_strings: List[str],
expected_values: List[float]):
test_model = self.INIBasedModelTest(id=self._random_string, float_value=self._random_float,
float_values=floats_as_strings)
@pytest.mark.parametrize(
"floats_as_strings, expected_values",
[
(["1d0", "1d-2"], [1e0, 1e-2]),
(["1d+2", "1.d+2", "-1.d-2"], [1e2, 1.0e2, -1.0e-2]),
],
)
def test_scientific_notation_for_list_of_float_field_is_parsed_as_list_of_floats(
self, floats_as_strings: List[str], expected_values: List[float]
):
test_model = self.INIBasedModelTest(
id=self._random_string,
float_value=self._random_float,
float_values=floats_as_strings,
)

assert test_model.id == self._random_string
assert test_model.float_value == pytest.approx(self._random_float)
assert test_model.float_values == pytest.approx(expected_values)

def test_setting_string_attribute_with_scientific_notation_correctly_parses_value(self):
test_model = self.INIBasedModelTest(id=self._random_string, float_value=self._random_float,
float_values=self._random_list_of_floats)
def test_setting_string_attribute_with_scientific_notation_correctly_parses_value(
self,
):
test_model = self.INIBasedModelTest(
id=self._random_string,
float_value=self._random_float,
float_values=self._random_list_of_floats,
)

test_model.id = "1d1"

assert test_model.id == "1d1"

def test_setting_float_attribute_with_scientific_notation_correctly_parses_value(self):
test_model = self.INIBasedModelTest(id=self._random_string, float_value=self._random_float,
float_values=self._random_list_of_floats)
def test_setting_float_attribute_with_scientific_notation_correctly_parses_value(
self,
):
test_model = self.INIBasedModelTest(
id=self._random_string,
float_value=self._random_float,
float_values=self._random_list_of_floats,
)

test_model.float_value = "1d1"

assert test_model.float_value == pytest.approx(1e1)

def test_setting_list_of_floats_attribute_with_scientific_notation_correctly_parses_values(self):
test_model = self.INIBasedModelTest(id=self._random_string, float_value=self._random_float,
float_values=self._random_list_of_floats)
def test_setting_list_of_floats_attribute_with_scientific_notation_correctly_parses_values(
self,
):
test_model = self.INIBasedModelTest(
id=self._random_string,
float_value=self._random_float,
float_values=self._random_list_of_floats,
)

test_model.float_values = ["1d1", "2d-1"]

Expand Down

0 comments on commit 395252a

Please sign in to comment.