Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
MAfarrag committed Jan 21, 2025
2 parents 04c398b + f4e77e8 commit feadac3
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 29 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.11", "3.12"]
python-version: ["3.9", "3.11", "3.12", "3.13"]
os: [ubuntu-latest, windows-latest, macos-13]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -23,7 +23,7 @@ jobs:
- name: Run image
uses: abatilo/actions-poetry@v2.3.0
with:
poetry-version: 1.8.3
poetry-version: 1.8.4
- name: Cache Poetry virtualenv
uses: actions/cache@v4
id: cache
Expand All @@ -49,7 +49,7 @@ jobs:
run: poetry run pytest --cov . --cov-report xml:coverage-reports/coverage-hydrolib-core.xml --junitxml=xunit-reports/xunit-result-hydrolib-core.xml

- name: Autoformat code if the check fails
if: ${{ (matrix.os == 'ubuntu-latest') && (matrix.python-version == 3.12) }}
if: ${{ (matrix.os == 'ubuntu-latest') && (matrix.python-version == 3.13) }}
run: |
poetry run isort .
poetry run black .
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: 3.12
python-version: 3.13

- name: Run image
uses: abatilo/actions-poetry@v2.3.0
with:
poetry-version: 1.8.3
poetry-version: 1.8.4
- name: Cache Poetry virtualenv
uses: actions/cache@v4
id: cache
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: 3.12
python-version: 3.13

- name: Run image
uses: abatilo/actions-poetry@v2.3.0
with:
poetry-version: 1.8.3
poetry-version: 1.8.4
- name: Cache Poetry virtualenv
uses: actions/cache@v4
id: cache
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.12]
python-version: [3.13]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -29,7 +29,7 @@ jobs:
- name: Run image
uses: abatilo/actions-poetry@v2.3.0
with:
poetry-version: 1.8.3
poetry-version: 1.8.4

- name: Cache Poetry virtualenv
uses: actions/cache@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ jobs:
- name: Set up python
uses: actions/setup-python@v5
with:
python-version: 3.12
python-version: 3.13

- name: Run image
uses: abatilo/actions-poetry@v2.3.0
with:
poetry-version: 1.8.3
poetry-version: 1.8.4

- name: Cache Poetry virtualenv
uses: actions/cache@v4
Expand Down
18 changes: 2 additions & 16 deletions hydrolib/core/dflowfm/ini/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from abc import ABC
from enum import Enum
from math import isnan
from re import compile
from typing import (
Any,
Callable,
Expand All @@ -29,6 +28,7 @@
ParsableFileModel,
)

from ...utils import FortranUtils
from ..ini.io_models import CommentBlock, Document, Property, Section
from .parser import Parser
from .serializer import (
Expand Down Expand Up @@ -58,9 +58,6 @@ 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 @@ -159,18 +156,7 @@ 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
return FortranUtils.replace_fortran_scientific_notation(value)

@classmethod
def validate(cls: Type["INIBasedModel"], value: Any) -> "INIBasedModel":
Expand Down
21 changes: 21 additions & 0 deletions hydrolib/core/dflowfm/tim/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pydantic.v1.class_validators import validator

from hydrolib.core.basemodel import BaseModel, ModelSaveSettings, ParsableFileModel
from hydrolib.core.utils import FortranUtils

from .parser import TimParser
from .serializer import TimSerializer, TimSerializerConfig
Expand Down Expand Up @@ -49,6 +50,26 @@ def _get_serializer(
def _get_parser(cls) -> Callable[[Path], Dict]:
return TimParser.parse

@validator("timeseries", pre=True, check_fields=True, allow_reuse=True)
def replace_fortran_scientific_notation_for_floats(cls, value, field):
for record in value:
if isinstance(record, dict):
record["time"] = FortranUtils.replace_fortran_scientific_notation(
record["time"]
)
record["data"] = FortranUtils.replace_fortran_scientific_notation(
record["data"]
)
elif isinstance(record, TimRecord):
record.time = FortranUtils.replace_fortran_scientific_notation(
record.time
)
record.data = FortranUtils.replace_fortran_scientific_notation(
record.data
)

return value

@validator("timeseries")
@classmethod
def _validate_timeseries_values(cls, v: List[TimRecord]) -> List[TimRecord]:
Expand Down
22 changes: 22 additions & 0 deletions hydrolib/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pathlib import Path
from typing import Any, Callable, List, Optional

from pydantic import validator
from pydantic.v1.fields import ModelField
from strenum import StrEnum


Expand Down Expand Up @@ -332,3 +334,23 @@ def _calculate_md5_checksum(filepath: Path) -> str:
for chunk in iter(lambda: file.read(4096), b""):
md5_hash.update(chunk)
return md5_hash.hexdigest()


class FortranUtils:
"""Utility class for Fortran specific conventions."""

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

@staticmethod
def replace_fortran_scientific_notation(value):
"""Replace Fortran scientific notation ("D" in exponent) with standard
scientific notation ("e" in exponent).
"""
if isinstance(value, str):
return FortranUtils._scientific_exp_d_notation_regex.sub(r"\1e\3", value)
elif isinstance(value, list):
return list(map(FortranUtils.replace_fortran_scientific_notation, value))

return value
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ python = "^3.9"
# exclude yanked netcdf versions 1.7.0 and 1.7.1, but include 1.7.2 (first with python 3.12 support)
netCDF4 = "^1.5,!=1.7.0,!=1.7.1"
# no caret here, since numpy v2 is required for future python 3.13 support, but this is not yet widely supported by packages numpy v1 support is also still required.
numpy = ">=1.25,<3"
numpy = [
{ version = ">=1.25,<3", python = "^3.9" },
{ version = "^2.1", python = "^3.13" }
]
pydantic = "^2.5"
# lxml 5.0 is from December 2023
lxml = "^5.0"
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ sonar.organization=deltares
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8

sonar.python.version=3.9, 3.10, 3.11, 3.12
sonar.python.version=3.9, 3.10, 3.11, 3.12, 3.13
2 changes: 2 additions & 0 deletions tests/data/input/tim/unimagdir.wnd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
0.0 1.00 270.00
9d9 1.00 270.00
9 changes: 9 additions & 0 deletions tests/dflowfm/test_tim.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
from pathlib import Path

import pytest
Expand Down Expand Up @@ -223,6 +224,14 @@ def test_validate_data_for_timeseries_throws_exception_for_incorrect_data(

assert expected_error_msg in str(error.value)

def test_test_fortran_d_exponent_supported(self):
input_path = Path(test_input_dir / "tim" / "unimagdir.wnd")
tim_model = TimModel(input_path)
assert tim_model.timeseries[0].time == 0
assert tim_model.timeseries[0].data == [1.0, 270.0]
assert math.isclose(tim_model.timeseries[1].time, 9e9)
assert tim_model.timeseries[1].data == [1.0, 270.0]


class TestTimRecord:
def test_initialization(self):
Expand Down

0 comments on commit feadac3

Please sign in to comment.