floodmodeller-api 0.4.2__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- floodmodeller_api/__init__.py +8 -9
- floodmodeller_api/_base.py +184 -176
- floodmodeller_api/backup.py +273 -273
- floodmodeller_api/dat.py +909 -838
- floodmodeller_api/diff.py +136 -119
- floodmodeller_api/ied.py +307 -311
- floodmodeller_api/ief.py +647 -646
- floodmodeller_api/ief_flags.py +253 -253
- floodmodeller_api/inp.py +266 -268
- floodmodeller_api/libs/libifcoremd.dll +0 -0
- floodmodeller_api/libs/libifcoremt.so.5 +0 -0
- floodmodeller_api/libs/libifport.so.5 +0 -0
- floodmodeller_api/{libmmd.dll → libs/libimf.so} +0 -0
- floodmodeller_api/libs/libintlc.so.5 +0 -0
- floodmodeller_api/libs/libmmd.dll +0 -0
- floodmodeller_api/libs/libsvml.so +0 -0
- floodmodeller_api/libs/libzzn_read.so +0 -0
- floodmodeller_api/libs/zzn_read.dll +0 -0
- floodmodeller_api/logs/__init__.py +2 -2
- floodmodeller_api/logs/lf.py +320 -314
- floodmodeller_api/logs/lf_helpers.py +354 -346
- floodmodeller_api/logs/lf_params.py +643 -529
- floodmodeller_api/mapping.py +84 -0
- floodmodeller_api/test/__init__.py +4 -4
- floodmodeller_api/test/conftest.py +9 -8
- floodmodeller_api/test/test_backup.py +117 -117
- floodmodeller_api/test/test_dat.py +221 -92
- floodmodeller_api/test/test_data/All Units 4_6.DAT +1081 -1081
- floodmodeller_api/test/test_data/All Units 4_6.feb +1081 -1081
- floodmodeller_api/test/test_data/BRIDGE.DAT +926 -926
- floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.dat +36 -36
- floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.feb +36 -36
- floodmodeller_api/test/test_data/DamBreakADI.xml +52 -52
- floodmodeller_api/test/test_data/DamBreakFAST.xml +58 -58
- floodmodeller_api/test/test_data/DamBreakFAST_dy.xml +53 -53
- floodmodeller_api/test/test_data/DamBreakTVD.xml +55 -55
- floodmodeller_api/test/test_data/DefenceBreach.xml +53 -53
- floodmodeller_api/test/test_data/DefenceBreachFAST.xml +60 -60
- floodmodeller_api/test/test_data/DefenceBreachFAST_dy.xml +55 -55
- floodmodeller_api/test/test_data/Domain1+2_QH.xml +76 -76
- floodmodeller_api/test/test_data/Domain1_H.xml +41 -41
- floodmodeller_api/test/test_data/Domain1_Q.xml +41 -41
- floodmodeller_api/test/test_data/Domain1_Q_FAST.xml +48 -48
- floodmodeller_api/test/test_data/Domain1_Q_FAST_dy.xml +48 -48
- floodmodeller_api/test/test_data/Domain1_Q_xml_expected.json +263 -0
- floodmodeller_api/test/test_data/Domain1_W.xml +41 -41
- floodmodeller_api/test/test_data/EX1.DAT +321 -321
- floodmodeller_api/test/test_data/EX1.ext +107 -107
- floodmodeller_api/test/test_data/EX1.feb +320 -320
- floodmodeller_api/test/test_data/EX1.gxy +107 -107
- floodmodeller_api/test/test_data/EX17.DAT +421 -422
- floodmodeller_api/test/test_data/EX17.ext +213 -213
- floodmodeller_api/test/test_data/EX17.feb +422 -422
- floodmodeller_api/test/test_data/EX18.DAT +375 -375
- floodmodeller_api/test/test_data/EX18_DAT_expected.json +3876 -0
- floodmodeller_api/test/test_data/EX2.DAT +302 -302
- floodmodeller_api/test/test_data/EX3.DAT +926 -926
- floodmodeller_api/test/test_data/EX3_DAT_expected.json +16235 -0
- floodmodeller_api/test/test_data/EX3_IEF_expected.json +61 -0
- floodmodeller_api/test/test_data/EX6.DAT +2084 -2084
- floodmodeller_api/test/test_data/EX6.ext +532 -532
- floodmodeller_api/test/test_data/EX6.feb +2084 -2084
- floodmodeller_api/test/test_data/EX6_DAT_expected.json +31647 -0
- floodmodeller_api/test/test_data/Event Data Example.DAT +336 -336
- floodmodeller_api/test/test_data/Event Data Example.ext +107 -107
- floodmodeller_api/test/test_data/Event Data Example.feb +336 -336
- floodmodeller_api/test/test_data/Linked1D2D.xml +52 -52
- floodmodeller_api/test/test_data/Linked1D2DFAST.xml +53 -53
- floodmodeller_api/test/test_data/Linked1D2DFAST_dy.xml +48 -48
- floodmodeller_api/test/test_data/Linked1D2D_xml_expected.json +313 -0
- floodmodeller_api/test/test_data/blockage.dat +50 -50
- floodmodeller_api/test/test_data/blockage.ext +45 -45
- floodmodeller_api/test/test_data/blockage.feb +9 -9
- floodmodeller_api/test/test_data/blockage.gxy +71 -71
- floodmodeller_api/test/test_data/defaultUnits.dat +127 -127
- floodmodeller_api/test/test_data/defaultUnits.ext +45 -45
- floodmodeller_api/test/test_data/defaultUnits.feb +9 -9
- floodmodeller_api/test/test_data/defaultUnits.fmpx +58 -58
- floodmodeller_api/test/test_data/defaultUnits.gxy +85 -85
- floodmodeller_api/test/test_data/ex3.ief +20 -20
- floodmodeller_api/test/test_data/ex3.lf1 +2800 -2800
- floodmodeller_api/test/test_data/ex4.DAT +1374 -1374
- floodmodeller_api/test/test_data/ex4_changed.DAT +1374 -1374
- floodmodeller_api/test/test_data/example1.inp +329 -329
- floodmodeller_api/test/test_data/example2.inp +158 -158
- floodmodeller_api/test/test_data/example3.inp +297 -297
- floodmodeller_api/test/test_data/example4.inp +388 -388
- floodmodeller_api/test/test_data/example5.inp +147 -147
- floodmodeller_api/test/test_data/example6.inp +154 -154
- floodmodeller_api/test/test_data/jump.dat +176 -176
- floodmodeller_api/test/test_data/network.dat +1374 -1374
- floodmodeller_api/test/test_data/network.ext +45 -45
- floodmodeller_api/test/test_data/network.exy +1 -1
- floodmodeller_api/test/test_data/network.feb +45 -45
- floodmodeller_api/test/test_data/network.ied +45 -45
- floodmodeller_api/test/test_data/network.ief +20 -20
- floodmodeller_api/test/test_data/network.inp +147 -147
- floodmodeller_api/test/test_data/network.pxy +57 -57
- floodmodeller_api/test/test_data/network.zzd +122 -122
- floodmodeller_api/test/test_data/network_dat_expected.json +21837 -0
- floodmodeller_api/test/test_data/network_from_tabularCSV.csv +87 -87
- floodmodeller_api/test/test_data/network_ied_expected.json +287 -0
- floodmodeller_api/test/test_data/rnweir.dat +9 -9
- floodmodeller_api/test/test_data/rnweir.ext +45 -45
- floodmodeller_api/test/test_data/rnweir.feb +9 -9
- floodmodeller_api/test/test_data/rnweir.gxy +45 -45
- floodmodeller_api/test/test_data/rnweir_default.dat +74 -74
- floodmodeller_api/test/test_data/rnweir_default.ext +45 -45
- floodmodeller_api/test/test_data/rnweir_default.feb +9 -9
- floodmodeller_api/test/test_data/rnweir_default.fmpx +58 -58
- floodmodeller_api/test/test_data/rnweir_default.gxy +53 -53
- floodmodeller_api/test/test_data/unit checks.dat +16 -16
- floodmodeller_api/test/test_ied.py +29 -29
- floodmodeller_api/test/test_ief.py +125 -24
- floodmodeller_api/test/test_inp.py +47 -48
- floodmodeller_api/test/test_json.py +114 -0
- floodmodeller_api/test/test_logs_lf.py +48 -51
- floodmodeller_api/test/test_tool.py +165 -154
- floodmodeller_api/test/test_toolbox_structure_log.py +234 -239
- floodmodeller_api/test/test_xml2d.py +151 -156
- floodmodeller_api/test/test_zzn.py +36 -34
- floodmodeller_api/to_from_json.py +218 -0
- floodmodeller_api/tool.py +332 -330
- floodmodeller_api/toolbox/__init__.py +5 -5
- floodmodeller_api/toolbox/example_tool.py +45 -45
- floodmodeller_api/toolbox/model_build/__init__.py +2 -2
- floodmodeller_api/toolbox/model_build/add_siltation_definition.py +100 -94
- floodmodeller_api/toolbox/model_build/structure_log/__init__.py +1 -1
- floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +287 -289
- floodmodeller_api/toolbox/model_build/structure_log_definition.py +76 -72
- floodmodeller_api/units/__init__.py +10 -10
- floodmodeller_api/units/_base.py +214 -209
- floodmodeller_api/units/boundaries.py +467 -469
- floodmodeller_api/units/comment.py +52 -55
- floodmodeller_api/units/conduits.py +382 -403
- floodmodeller_api/units/helpers.py +123 -132
- floodmodeller_api/units/iic.py +107 -101
- floodmodeller_api/units/losses.py +305 -308
- floodmodeller_api/units/sections.py +444 -445
- floodmodeller_api/units/structures.py +1690 -1684
- floodmodeller_api/units/units.py +93 -102
- floodmodeller_api/units/unsupported.py +44 -44
- floodmodeller_api/units/variables.py +87 -89
- floodmodeller_api/urban1d/__init__.py +11 -11
- floodmodeller_api/urban1d/_base.py +188 -177
- floodmodeller_api/urban1d/conduits.py +93 -85
- floodmodeller_api/urban1d/general_parameters.py +58 -58
- floodmodeller_api/urban1d/junctions.py +81 -79
- floodmodeller_api/urban1d/losses.py +81 -74
- floodmodeller_api/urban1d/outfalls.py +114 -107
- floodmodeller_api/urban1d/raingauges.py +111 -108
- floodmodeller_api/urban1d/subsections.py +92 -93
- floodmodeller_api/urban1d/xsections.py +147 -141
- floodmodeller_api/util.py +77 -21
- floodmodeller_api/validation/parameters.py +660 -660
- floodmodeller_api/validation/urban_parameters.py +388 -404
- floodmodeller_api/validation/validation.py +110 -112
- floodmodeller_api/version.py +1 -1
- floodmodeller_api/xml2d.py +688 -684
- floodmodeller_api/xml2d_template.py +37 -37
- floodmodeller_api/zzn.py +387 -365
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/LICENSE.txt +13 -13
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/METADATA +82 -82
- floodmodeller_api-0.4.3.dist-info/RECORD +179 -0
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/WHEEL +1 -1
- floodmodeller_api-0.4.3.dist-info/entry_points.txt +3 -0
- floodmodeller_api/libifcoremd.dll +0 -0
- floodmodeller_api/test/test_data/EX3.bmp +0 -0
- floodmodeller_api/test/test_data/test_output.csv +0 -87
- floodmodeller_api/zzn_read.dll +0 -0
- floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.py +0 -3
- floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.py +0 -3
- floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.py +0 -41
- floodmodeller_api-0.4.2.dist-info/RECORD +0 -169
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,24 +1,125 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@pytest.fixture
|
|
15
|
-
def
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from unittest.mock import call, patch
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from floodmodeller_api import IEF
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture()
|
|
10
|
+
def ief_fp(test_workspace: str) -> Path:
|
|
11
|
+
return Path(test_workspace, "network.ief")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture()
|
|
15
|
+
def ief(ief_fp: Path) -> IEF:
|
|
16
|
+
return IEF(ief_fp)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture()
|
|
20
|
+
def data_before(ief_fp: Path) -> str:
|
|
21
|
+
with open(ief_fp) as ief_file:
|
|
22
|
+
return ief_file.read()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture()
|
|
26
|
+
def exe_bin(tmpdir) -> Path:
|
|
27
|
+
for exe in ["ISISf32.exe", "ISISf32_DoubleP.exe"]:
|
|
28
|
+
exe_path = Path(tmpdir, exe)
|
|
29
|
+
exe_path.touch()
|
|
30
|
+
return Path(tmpdir)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_ief_open_does_not_change_data(ief: IEF, data_before: str):
|
|
34
|
+
"""IEF: Test str representation equal to ief file with no changes"""
|
|
35
|
+
assert ief._write() == data_before
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.parametrize(
|
|
39
|
+
("precision", "method", "amend", "exe"),
|
|
40
|
+
[
|
|
41
|
+
("DEFAULT", "WAIT", False, "ISISf32.exe"),
|
|
42
|
+
("DEFAULT", "WAIT", True, "ISISf32_DoubleP.exe"),
|
|
43
|
+
("SINGLE", "WAIT", False, "ISISf32.exe"),
|
|
44
|
+
("SINGLE", "WAIT", True, "ISISf32.exe"),
|
|
45
|
+
("DOUBLE", "WAIT", False, "ISISf32_DoubleP.exe"),
|
|
46
|
+
("DOUBLE", "WAIT", True, "ISISf32_DoubleP.exe"),
|
|
47
|
+
("DEFAULT", "RETURN_PROCESS", False, "ISISf32.exe"),
|
|
48
|
+
("DEFAULT", "RETURN_PROCESS", True, "ISISf32_DoubleP.exe"),
|
|
49
|
+
("SINGLE", "RETURN_PROCESS", False, "ISISf32.exe"),
|
|
50
|
+
("SINGLE", "RETURN_PROCESS", True, "ISISf32.exe"),
|
|
51
|
+
("DOUBLE", "RETURN_PROCESS", False, "ISISf32_DoubleP.exe"),
|
|
52
|
+
("DOUBLE", "RETURN_PROCESS", True, "ISISf32_DoubleP.exe"),
|
|
53
|
+
],
|
|
54
|
+
)
|
|
55
|
+
def test_simulate(
|
|
56
|
+
ief: IEF,
|
|
57
|
+
ief_fp: Path,
|
|
58
|
+
exe_bin: Path,
|
|
59
|
+
precision: str,
|
|
60
|
+
method: str,
|
|
61
|
+
amend: bool,
|
|
62
|
+
exe: str,
|
|
63
|
+
):
|
|
64
|
+
if amend:
|
|
65
|
+
ief.launchdoubleprecisionversion = 1
|
|
66
|
+
|
|
67
|
+
with (
|
|
68
|
+
patch("floodmodeller_api.ief.Popen") as p_open,
|
|
69
|
+
patch("floodmodeller_api.ief.IEF.LOG_TIMEOUT", new=0),
|
|
70
|
+
patch("floodmodeller_api.ief.time.sleep") as sleep,
|
|
71
|
+
):
|
|
72
|
+
p_open.return_value.poll.side_effect = [None, None, 0]
|
|
73
|
+
|
|
74
|
+
exe_path = Path(exe_bin, exe)
|
|
75
|
+
ief.simulate(method=method, precision=precision, enginespath=str(exe_bin))
|
|
76
|
+
|
|
77
|
+
p_open.assert_called_once_with(f'"{exe_path}" -sd "{ief_fp}"', cwd=str(ief_fp.parent))
|
|
78
|
+
|
|
79
|
+
if method == "WAIT":
|
|
80
|
+
assert p_open.return_value.poll.call_count == 3
|
|
81
|
+
assert sleep.call_args_list[-3:] == [call(0.1), call(1), call(1)]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_simulate_error_without_bin(tmpdir, ief: IEF):
|
|
85
|
+
msg = (
|
|
86
|
+
r"\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
|
87
|
+
r"\nAPI Error: Problem encountered when trying to simulate IEF file .*\."
|
|
88
|
+
r"\n"
|
|
89
|
+
r"\nDetails: .*-floodmodeller_api/ief\.py-\d+"
|
|
90
|
+
r"\nMsg: Flood Modeller non-default engine path not found! .*"
|
|
91
|
+
r"\n"
|
|
92
|
+
r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
|
|
93
|
+
)
|
|
94
|
+
with pytest.raises(Exception, match=msg):
|
|
95
|
+
ief.simulate(enginespath=str(Path(tmpdir, "bin")))
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_simulate_error_without_exe(tmpdir, ief: IEF):
|
|
99
|
+
msg = (
|
|
100
|
+
r"\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
|
101
|
+
r"\nAPI Error: Problem encountered when trying to simulate IEF file .*\."
|
|
102
|
+
r"\n"
|
|
103
|
+
r"\nDetails: .*-floodmodeller_api/ief\.py-\d+"
|
|
104
|
+
r"\nMsg: Flood Modeller engine not found! Expected location: .*"
|
|
105
|
+
r"\n"
|
|
106
|
+
r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
|
|
107
|
+
)
|
|
108
|
+
with pytest.raises(Exception, match=msg):
|
|
109
|
+
ief.simulate(enginespath=str(tmpdir))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_simulate_error_without_save():
|
|
113
|
+
ief = IEF()
|
|
114
|
+
ief._filepath = None
|
|
115
|
+
msg = (
|
|
116
|
+
r"\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
|
117
|
+
r"\nAPI Error: Problem encountered when trying to simulate IEF file .*\."
|
|
118
|
+
r"\n"
|
|
119
|
+
r"\nDetails: .*-floodmodeller_api/ief\.py-\d+"
|
|
120
|
+
r"\nMsg: IEF must be saved to a specific filepath before simulate\(\) can be called\."
|
|
121
|
+
r"\n"
|
|
122
|
+
r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
|
|
123
|
+
)
|
|
124
|
+
with pytest.raises(Exception, match=msg):
|
|
125
|
+
ief.simulate()
|
|
@@ -1,48 +1,47 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
inp
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
inp.raingauges["1"].
|
|
31
|
-
inp.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
inp.raingauges["check"].
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
inp.save(
|
|
46
|
-
second_output = INP(
|
|
47
|
-
assert first_output == second_output
|
|
48
|
-
os.remove("__temp.inp")
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from floodmodeller_api import INP
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def inp_fp(test_workspace):
|
|
10
|
+
return Path(test_workspace, "network.inp")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def data_before(inp_fp):
|
|
15
|
+
return INP(inp_fp)._write()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_inp_open_does_not_change_data(inp_fp, data_before):
|
|
19
|
+
"""INP: Test str representation equal to inp file with no changes"""
|
|
20
|
+
inp = INP(inp_fp)
|
|
21
|
+
assert inp._write() == data_before
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_section_name_and_snow_catch_factor_changes(inp_fp, data_before):
|
|
25
|
+
"""INP: Test changing and reverting section name and snow catch factor makes no changes"""
|
|
26
|
+
inp = INP(inp_fp)
|
|
27
|
+
prev_name = inp.raingauges["1"].name
|
|
28
|
+
prev_scf = inp.raingauges["1"].snow_catch_factor
|
|
29
|
+
inp.raingauges["1"].name = "check"
|
|
30
|
+
inp.raingauges["1"].snow_catch_factor = 1.5
|
|
31
|
+
assert inp._write() != data_before
|
|
32
|
+
|
|
33
|
+
inp.raingauges["check"].name = prev_name
|
|
34
|
+
inp.raingauges["check"].snow_catch_factor = prev_scf
|
|
35
|
+
|
|
36
|
+
assert inp._write() == data_before
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_all_inp_files_in_folder_have_same_output(test_workspace, tmpdir):
|
|
40
|
+
"""INP: Check all '.inp' files in folder by reading the _write() output into a new INP instance and checking it stays the same."""
|
|
41
|
+
for inpfile in Path(test_workspace).glob("*.inp"):
|
|
42
|
+
inp = INP(inpfile)
|
|
43
|
+
first_output = inp._write()
|
|
44
|
+
new_path = Path(tmpdir) / "tmp.inp"
|
|
45
|
+
inp.save(new_path)
|
|
46
|
+
second_output = INP(new_path)._write()
|
|
47
|
+
assert first_output == second_output
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from floodmodeller_api import DAT, IED, IEF, INP, XML2D
|
|
8
|
+
from floodmodeller_api.to_from_json import is_jsonable
|
|
9
|
+
from floodmodeller_api.util import read_file
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_expected_json_files():
|
|
13
|
+
"""Helper function to recreate all the expected JSON files if needed at any point due to updates
|
|
14
|
+
to the to_json code"""
|
|
15
|
+
|
|
16
|
+
test_workspace = Path(os.path.dirname(__file__), "test_data")
|
|
17
|
+
for file in [
|
|
18
|
+
"network.dat",
|
|
19
|
+
"network.ied",
|
|
20
|
+
"EX3.DAT",
|
|
21
|
+
"EX6.DAT",
|
|
22
|
+
"EX18.DAT",
|
|
23
|
+
"EX3.IEF",
|
|
24
|
+
"Domain1_Q.xml",
|
|
25
|
+
"Linked1D2D.xml",
|
|
26
|
+
]:
|
|
27
|
+
file = Path(test_workspace, file)
|
|
28
|
+
obj = read_file(file)
|
|
29
|
+
new_file = file.with_name(f"{file.name.replace('.', '_')}_expected").with_suffix(".json")
|
|
30
|
+
with open(new_file, "w") as json_file:
|
|
31
|
+
json_file.write(obj.to_json())
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@pytest.fixture
|
|
35
|
+
def dat_obj(test_workspace):
|
|
36
|
+
"""JSON: To create the dat object for the tests"""
|
|
37
|
+
return DAT(Path(test_workspace, "EX18.DAT"))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.fixture
|
|
41
|
+
def json_expected(test_workspace):
|
|
42
|
+
"""JSON: expected after passing to_json method"""
|
|
43
|
+
return Path(test_workspace, "EX18_DAT_expected.json")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_dat_json(dat_obj):
|
|
47
|
+
"""JSON: To test if to_json runs without failing"""
|
|
48
|
+
assert dat_obj.to_json()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.fixture
|
|
52
|
+
def parameterised_objs_and_expected(test_workspace):
|
|
53
|
+
"""JSON: expected after passing to_json method"""
|
|
54
|
+
return [
|
|
55
|
+
(DAT(test_workspace / "EX18.DAT"), test_workspace / "EX18_DAT_expected.json"),
|
|
56
|
+
(DAT(test_workspace / "network.dat"), test_workspace / "network_dat_expected.json"),
|
|
57
|
+
(IED(test_workspace / "network.ied"), test_workspace / "network_ied_expected.json"),
|
|
58
|
+
(DAT(test_workspace / "EX3.DAT"), test_workspace / "EX3_DAT_expected.json"),
|
|
59
|
+
(DAT(test_workspace / "EX6.DAT"), test_workspace / "EX6_DAT_expected.json"),
|
|
60
|
+
(IEF(test_workspace / "ex3.ief"), test_workspace / "EX3_IEF_expected.json"),
|
|
61
|
+
(XML2D(test_workspace / "Domain1_Q.xml"), test_workspace / "Domain1_Q_xml_expected.json"),
|
|
62
|
+
(XML2D(test_workspace / "Linked1D2D.xml"), test_workspace / "Linked1D2D_xml_expected.json"),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_to_json_matches_expected(parameterised_objs_and_expected):
|
|
67
|
+
"""JSON: To test if the json object produced in to_json is identical to the expected json file"""
|
|
68
|
+
for obj, json_expected in parameterised_objs_and_expected:
|
|
69
|
+
# First, to create and handle the json (str) object
|
|
70
|
+
# Fetch "Object Attributes" key only as we don't need to compare API versions
|
|
71
|
+
json_dict_from_obj = json.loads(obj.to_json())["Object Attributes"]
|
|
72
|
+
|
|
73
|
+
# Second, to handle the json file ..._expected.json which must be the same as the object created above.
|
|
74
|
+
json_dict_from_file = json.load(open(json_expected))["Object Attributes"] # noqa: SIM115
|
|
75
|
+
|
|
76
|
+
# keys to ignore when testing for equivalence
|
|
77
|
+
keys_to_remove = ["_filepath", "file", "_log_path"]
|
|
78
|
+
for key in keys_to_remove:
|
|
79
|
+
json_dict_from_obj.pop(key, None)
|
|
80
|
+
json_dict_from_file.pop(key, None)
|
|
81
|
+
|
|
82
|
+
assert json_dict_from_obj == json_dict_from_file
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@pytest.mark.parametrize(
|
|
86
|
+
"api_class,file_extension_glob",
|
|
87
|
+
[
|
|
88
|
+
(DAT, "*.dat"),
|
|
89
|
+
(IED, "*.ied"),
|
|
90
|
+
(XML2D, "*.xml"),
|
|
91
|
+
(IEF, "*.ief"),
|
|
92
|
+
(INP, "*.inp"),
|
|
93
|
+
],
|
|
94
|
+
)
|
|
95
|
+
def test_obj_reproduces_from_json_for_all_test_api_files(
|
|
96
|
+
test_workspace,
|
|
97
|
+
api_class,
|
|
98
|
+
file_extension_glob,
|
|
99
|
+
):
|
|
100
|
+
"""JSON: To test the from_json function, It should produce the same dat file from a json file"""
|
|
101
|
+
for file in Path(test_workspace).glob(file_extension_glob):
|
|
102
|
+
assert api_class(file) == api_class.from_json(api_class(file).to_json())
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_is_jsonable_with_jsonable_object():
|
|
106
|
+
assert is_jsonable({"a": 1, "b": 2})
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_is_jsonable_with_non_jsonable_object():
|
|
110
|
+
class NonJsonable:
|
|
111
|
+
def __init__(self):
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
assert not is_jsonable(NonJsonable())
|
|
@@ -1,51 +1,48 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
from floodmodeller_api import IEF, LF1
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@pytest.fixture
|
|
10
|
-
def lf1_fp(test_workspace):
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def test_lf1_info_dict(lf1_fp):
|
|
15
|
-
"""LF1: Check info dictionary"""
|
|
16
|
-
lf1 = LF1(lf1_fp)
|
|
17
|
-
assert lf1.info["version"] == "5.0.0.7752"
|
|
18
|
-
assert lf1.info["max_system_volume"] == 270549
|
|
19
|
-
assert lf1.info["mass_balance_error"] == -0.03
|
|
20
|
-
assert lf1.info["progress"] == 100
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_lf1_report_progress(lf1_fp):
|
|
24
|
-
"""LF1: Check report_progress()"""
|
|
25
|
-
lf1 = LF1(lf1_fp)
|
|
26
|
-
assert lf1.report_progress() == 100
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def test_lf1_to_dataframe(lf1_fp):
|
|
30
|
-
"""LF1: Check to_dataframe()"""
|
|
31
|
-
lf1 = LF1(lf1_fp)
|
|
32
|
-
df = lf1.to_dataframe()
|
|
33
|
-
assert df.
|
|
34
|
-
assert df.
|
|
35
|
-
assert df.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def test_lf1_from_ief(lf1_fp, test_workspace):
|
|
39
|
-
"""LF1: Check IEF.get_lf1()"""
|
|
40
|
-
lf1 = LF1(lf1_fp)
|
|
41
|
-
|
|
42
|
-
ief_fp =
|
|
43
|
-
ief = IEF(ief_fp)
|
|
44
|
-
lf1_from_ief = ief.get_log()
|
|
45
|
-
|
|
46
|
-
assert lf1._filepath == lf1_from_ief._filepath
|
|
47
|
-
assert lf1.info == lf1_from_ief.info
|
|
48
|
-
|
|
49
|
-
pd.testing.assert_frame_equal(lf1.to_dataframe(), lf1_from_ief.to_dataframe())
|
|
50
|
-
except Exception:
|
|
51
|
-
pytest.fail("Dataframes not equal")
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from floodmodeller_api import IEF, LF1
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def lf1_fp(test_workspace):
|
|
11
|
+
return Path(test_workspace, "ex3.lf1")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_lf1_info_dict(lf1_fp):
|
|
15
|
+
"""LF1: Check info dictionary"""
|
|
16
|
+
lf1 = LF1(lf1_fp)
|
|
17
|
+
assert lf1.info["version"] == "5.0.0.7752"
|
|
18
|
+
assert lf1.info["max_system_volume"] == 270549
|
|
19
|
+
assert lf1.info["mass_balance_error"] == -0.03
|
|
20
|
+
assert lf1.info["progress"] == 100
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_lf1_report_progress(lf1_fp):
|
|
24
|
+
"""LF1: Check report_progress()"""
|
|
25
|
+
lf1 = LF1(lf1_fp)
|
|
26
|
+
assert lf1.report_progress() == 100
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_lf1_to_dataframe(lf1_fp):
|
|
30
|
+
"""LF1: Check to_dataframe()"""
|
|
31
|
+
lf1 = LF1(lf1_fp)
|
|
32
|
+
df = lf1.to_dataframe()
|
|
33
|
+
assert df.loc[df.index[0], "iter"] == 6
|
|
34
|
+
assert df.loc[df.index[-1], "outflow"] == 21.06
|
|
35
|
+
assert df.loc[df.index[4], "mass_error"] == -0.07
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_lf1_from_ief(lf1_fp, test_workspace):
|
|
39
|
+
"""LF1: Check IEF.get_lf1()"""
|
|
40
|
+
lf1 = LF1(lf1_fp)
|
|
41
|
+
|
|
42
|
+
ief_fp = Path(test_workspace, "ex3.ief")
|
|
43
|
+
ief = IEF(ief_fp)
|
|
44
|
+
lf1_from_ief = ief.get_log()
|
|
45
|
+
|
|
46
|
+
assert lf1._filepath == lf1_from_ief._filepath
|
|
47
|
+
assert lf1.info == lf1_from_ief.info
|
|
48
|
+
pd.testing.assert_frame_equal(lf1.to_dataframe(), lf1_from_ief.to_dataframe())
|