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.
Files changed (178) hide show
  1. floodmodeller_api/__init__.py +8 -9
  2. floodmodeller_api/_base.py +184 -176
  3. floodmodeller_api/backup.py +273 -273
  4. floodmodeller_api/dat.py +909 -838
  5. floodmodeller_api/diff.py +136 -119
  6. floodmodeller_api/ied.py +307 -311
  7. floodmodeller_api/ief.py +647 -646
  8. floodmodeller_api/ief_flags.py +253 -253
  9. floodmodeller_api/inp.py +266 -268
  10. floodmodeller_api/libs/libifcoremd.dll +0 -0
  11. floodmodeller_api/libs/libifcoremt.so.5 +0 -0
  12. floodmodeller_api/libs/libifport.so.5 +0 -0
  13. floodmodeller_api/{libmmd.dll → libs/libimf.so} +0 -0
  14. floodmodeller_api/libs/libintlc.so.5 +0 -0
  15. floodmodeller_api/libs/libmmd.dll +0 -0
  16. floodmodeller_api/libs/libsvml.so +0 -0
  17. floodmodeller_api/libs/libzzn_read.so +0 -0
  18. floodmodeller_api/libs/zzn_read.dll +0 -0
  19. floodmodeller_api/logs/__init__.py +2 -2
  20. floodmodeller_api/logs/lf.py +320 -314
  21. floodmodeller_api/logs/lf_helpers.py +354 -346
  22. floodmodeller_api/logs/lf_params.py +643 -529
  23. floodmodeller_api/mapping.py +84 -0
  24. floodmodeller_api/test/__init__.py +4 -4
  25. floodmodeller_api/test/conftest.py +9 -8
  26. floodmodeller_api/test/test_backup.py +117 -117
  27. floodmodeller_api/test/test_dat.py +221 -92
  28. floodmodeller_api/test/test_data/All Units 4_6.DAT +1081 -1081
  29. floodmodeller_api/test/test_data/All Units 4_6.feb +1081 -1081
  30. floodmodeller_api/test/test_data/BRIDGE.DAT +926 -926
  31. floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.dat +36 -36
  32. floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.feb +36 -36
  33. floodmodeller_api/test/test_data/DamBreakADI.xml +52 -52
  34. floodmodeller_api/test/test_data/DamBreakFAST.xml +58 -58
  35. floodmodeller_api/test/test_data/DamBreakFAST_dy.xml +53 -53
  36. floodmodeller_api/test/test_data/DamBreakTVD.xml +55 -55
  37. floodmodeller_api/test/test_data/DefenceBreach.xml +53 -53
  38. floodmodeller_api/test/test_data/DefenceBreachFAST.xml +60 -60
  39. floodmodeller_api/test/test_data/DefenceBreachFAST_dy.xml +55 -55
  40. floodmodeller_api/test/test_data/Domain1+2_QH.xml +76 -76
  41. floodmodeller_api/test/test_data/Domain1_H.xml +41 -41
  42. floodmodeller_api/test/test_data/Domain1_Q.xml +41 -41
  43. floodmodeller_api/test/test_data/Domain1_Q_FAST.xml +48 -48
  44. floodmodeller_api/test/test_data/Domain1_Q_FAST_dy.xml +48 -48
  45. floodmodeller_api/test/test_data/Domain1_Q_xml_expected.json +263 -0
  46. floodmodeller_api/test/test_data/Domain1_W.xml +41 -41
  47. floodmodeller_api/test/test_data/EX1.DAT +321 -321
  48. floodmodeller_api/test/test_data/EX1.ext +107 -107
  49. floodmodeller_api/test/test_data/EX1.feb +320 -320
  50. floodmodeller_api/test/test_data/EX1.gxy +107 -107
  51. floodmodeller_api/test/test_data/EX17.DAT +421 -422
  52. floodmodeller_api/test/test_data/EX17.ext +213 -213
  53. floodmodeller_api/test/test_data/EX17.feb +422 -422
  54. floodmodeller_api/test/test_data/EX18.DAT +375 -375
  55. floodmodeller_api/test/test_data/EX18_DAT_expected.json +3876 -0
  56. floodmodeller_api/test/test_data/EX2.DAT +302 -302
  57. floodmodeller_api/test/test_data/EX3.DAT +926 -926
  58. floodmodeller_api/test/test_data/EX3_DAT_expected.json +16235 -0
  59. floodmodeller_api/test/test_data/EX3_IEF_expected.json +61 -0
  60. floodmodeller_api/test/test_data/EX6.DAT +2084 -2084
  61. floodmodeller_api/test/test_data/EX6.ext +532 -532
  62. floodmodeller_api/test/test_data/EX6.feb +2084 -2084
  63. floodmodeller_api/test/test_data/EX6_DAT_expected.json +31647 -0
  64. floodmodeller_api/test/test_data/Event Data Example.DAT +336 -336
  65. floodmodeller_api/test/test_data/Event Data Example.ext +107 -107
  66. floodmodeller_api/test/test_data/Event Data Example.feb +336 -336
  67. floodmodeller_api/test/test_data/Linked1D2D.xml +52 -52
  68. floodmodeller_api/test/test_data/Linked1D2DFAST.xml +53 -53
  69. floodmodeller_api/test/test_data/Linked1D2DFAST_dy.xml +48 -48
  70. floodmodeller_api/test/test_data/Linked1D2D_xml_expected.json +313 -0
  71. floodmodeller_api/test/test_data/blockage.dat +50 -50
  72. floodmodeller_api/test/test_data/blockage.ext +45 -45
  73. floodmodeller_api/test/test_data/blockage.feb +9 -9
  74. floodmodeller_api/test/test_data/blockage.gxy +71 -71
  75. floodmodeller_api/test/test_data/defaultUnits.dat +127 -127
  76. floodmodeller_api/test/test_data/defaultUnits.ext +45 -45
  77. floodmodeller_api/test/test_data/defaultUnits.feb +9 -9
  78. floodmodeller_api/test/test_data/defaultUnits.fmpx +58 -58
  79. floodmodeller_api/test/test_data/defaultUnits.gxy +85 -85
  80. floodmodeller_api/test/test_data/ex3.ief +20 -20
  81. floodmodeller_api/test/test_data/ex3.lf1 +2800 -2800
  82. floodmodeller_api/test/test_data/ex4.DAT +1374 -1374
  83. floodmodeller_api/test/test_data/ex4_changed.DAT +1374 -1374
  84. floodmodeller_api/test/test_data/example1.inp +329 -329
  85. floodmodeller_api/test/test_data/example2.inp +158 -158
  86. floodmodeller_api/test/test_data/example3.inp +297 -297
  87. floodmodeller_api/test/test_data/example4.inp +388 -388
  88. floodmodeller_api/test/test_data/example5.inp +147 -147
  89. floodmodeller_api/test/test_data/example6.inp +154 -154
  90. floodmodeller_api/test/test_data/jump.dat +176 -176
  91. floodmodeller_api/test/test_data/network.dat +1374 -1374
  92. floodmodeller_api/test/test_data/network.ext +45 -45
  93. floodmodeller_api/test/test_data/network.exy +1 -1
  94. floodmodeller_api/test/test_data/network.feb +45 -45
  95. floodmodeller_api/test/test_data/network.ied +45 -45
  96. floodmodeller_api/test/test_data/network.ief +20 -20
  97. floodmodeller_api/test/test_data/network.inp +147 -147
  98. floodmodeller_api/test/test_data/network.pxy +57 -57
  99. floodmodeller_api/test/test_data/network.zzd +122 -122
  100. floodmodeller_api/test/test_data/network_dat_expected.json +21837 -0
  101. floodmodeller_api/test/test_data/network_from_tabularCSV.csv +87 -87
  102. floodmodeller_api/test/test_data/network_ied_expected.json +287 -0
  103. floodmodeller_api/test/test_data/rnweir.dat +9 -9
  104. floodmodeller_api/test/test_data/rnweir.ext +45 -45
  105. floodmodeller_api/test/test_data/rnweir.feb +9 -9
  106. floodmodeller_api/test/test_data/rnweir.gxy +45 -45
  107. floodmodeller_api/test/test_data/rnweir_default.dat +74 -74
  108. floodmodeller_api/test/test_data/rnweir_default.ext +45 -45
  109. floodmodeller_api/test/test_data/rnweir_default.feb +9 -9
  110. floodmodeller_api/test/test_data/rnweir_default.fmpx +58 -58
  111. floodmodeller_api/test/test_data/rnweir_default.gxy +53 -53
  112. floodmodeller_api/test/test_data/unit checks.dat +16 -16
  113. floodmodeller_api/test/test_ied.py +29 -29
  114. floodmodeller_api/test/test_ief.py +125 -24
  115. floodmodeller_api/test/test_inp.py +47 -48
  116. floodmodeller_api/test/test_json.py +114 -0
  117. floodmodeller_api/test/test_logs_lf.py +48 -51
  118. floodmodeller_api/test/test_tool.py +165 -154
  119. floodmodeller_api/test/test_toolbox_structure_log.py +234 -239
  120. floodmodeller_api/test/test_xml2d.py +151 -156
  121. floodmodeller_api/test/test_zzn.py +36 -34
  122. floodmodeller_api/to_from_json.py +218 -0
  123. floodmodeller_api/tool.py +332 -330
  124. floodmodeller_api/toolbox/__init__.py +5 -5
  125. floodmodeller_api/toolbox/example_tool.py +45 -45
  126. floodmodeller_api/toolbox/model_build/__init__.py +2 -2
  127. floodmodeller_api/toolbox/model_build/add_siltation_definition.py +100 -94
  128. floodmodeller_api/toolbox/model_build/structure_log/__init__.py +1 -1
  129. floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +287 -289
  130. floodmodeller_api/toolbox/model_build/structure_log_definition.py +76 -72
  131. floodmodeller_api/units/__init__.py +10 -10
  132. floodmodeller_api/units/_base.py +214 -209
  133. floodmodeller_api/units/boundaries.py +467 -469
  134. floodmodeller_api/units/comment.py +52 -55
  135. floodmodeller_api/units/conduits.py +382 -403
  136. floodmodeller_api/units/helpers.py +123 -132
  137. floodmodeller_api/units/iic.py +107 -101
  138. floodmodeller_api/units/losses.py +305 -308
  139. floodmodeller_api/units/sections.py +444 -445
  140. floodmodeller_api/units/structures.py +1690 -1684
  141. floodmodeller_api/units/units.py +93 -102
  142. floodmodeller_api/units/unsupported.py +44 -44
  143. floodmodeller_api/units/variables.py +87 -89
  144. floodmodeller_api/urban1d/__init__.py +11 -11
  145. floodmodeller_api/urban1d/_base.py +188 -177
  146. floodmodeller_api/urban1d/conduits.py +93 -85
  147. floodmodeller_api/urban1d/general_parameters.py +58 -58
  148. floodmodeller_api/urban1d/junctions.py +81 -79
  149. floodmodeller_api/urban1d/losses.py +81 -74
  150. floodmodeller_api/urban1d/outfalls.py +114 -107
  151. floodmodeller_api/urban1d/raingauges.py +111 -108
  152. floodmodeller_api/urban1d/subsections.py +92 -93
  153. floodmodeller_api/urban1d/xsections.py +147 -141
  154. floodmodeller_api/util.py +77 -21
  155. floodmodeller_api/validation/parameters.py +660 -660
  156. floodmodeller_api/validation/urban_parameters.py +388 -404
  157. floodmodeller_api/validation/validation.py +110 -112
  158. floodmodeller_api/version.py +1 -1
  159. floodmodeller_api/xml2d.py +688 -684
  160. floodmodeller_api/xml2d_template.py +37 -37
  161. floodmodeller_api/zzn.py +387 -365
  162. {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/LICENSE.txt +13 -13
  163. {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/METADATA +82 -82
  164. floodmodeller_api-0.4.3.dist-info/RECORD +179 -0
  165. {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/WHEEL +1 -1
  166. floodmodeller_api-0.4.3.dist-info/entry_points.txt +3 -0
  167. floodmodeller_api/libifcoremd.dll +0 -0
  168. floodmodeller_api/test/test_data/EX3.bmp +0 -0
  169. floodmodeller_api/test/test_data/test_output.csv +0 -87
  170. floodmodeller_api/zzn_read.dll +0 -0
  171. floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.bat +0 -2
  172. floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.py +0 -3
  173. floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.bat +0 -2
  174. floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.py +0 -3
  175. floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.bat +0 -2
  176. floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.py +0 -41
  177. floodmodeller_api-0.4.2.dist-info/RECORD +0 -169
  178. {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 os
2
-
3
- import pytest
4
-
5
- from floodmodeller_api import IEF
6
-
7
-
8
- @pytest.fixture
9
- def ief_fp(test_workspace):
10
- ief_fp = os.path.join(test_workspace, "network.ief")
11
- return ief_fp
12
-
13
-
14
- @pytest.fixture
15
- def data_before(ief_fp):
16
- with open(ief_fp, "r") as ief_file:
17
- data_before = ief_file.read()
18
- return data_before
19
-
20
-
21
- def test_ief_open_does_not_change_data(ief_fp, data_before):
22
- """IEF: Test str representation equal to ief file with no changes"""
23
- ief = IEF(ief_fp)
24
- assert ief._write() == data_before
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 os
2
- from pathlib import Path
3
-
4
- import pytest
5
-
6
- from floodmodeller_api import INP
7
-
8
-
9
- @pytest.fixture
10
- def inp_fp(test_workspace):
11
- return os.path.join(test_workspace, "network.inp")
12
-
13
-
14
- @pytest.fixture
15
- def data_before(inp_fp):
16
- return INP(inp_fp)._write()
17
-
18
-
19
- def test_inp_open_does_not_change_data(inp_fp, data_before):
20
- """INP: Test str representation equal to inp file with no changes"""
21
- inp = INP(inp_fp)
22
- assert inp._write() == data_before
23
-
24
-
25
- def test_section_name_and_snow_catch_factor_changes(inp_fp, data_before):
26
- """INP: Test changing and reverting section name and snow catch factor makes no changes"""
27
- inp = INP(inp_fp)
28
- prev_name = inp.raingauges["1"].name
29
- prev_scf = inp.raingauges["1"].snow_catch_factor
30
- inp.raingauges["1"].name = "check"
31
- inp.raingauges["1"].snow_catch_factor = 1.5
32
- assert inp._write() != data_before
33
-
34
- inp.raingauges["check"].name = prev_name
35
- inp.raingauges["check"].snow_catch_factor = prev_scf
36
-
37
- assert inp._write() == data_before
38
-
39
-
40
- def test_all_inp_files_in_folder_have_same_output(test_workspace):
41
- """INP: Check all '.inp' files in folder by reading the _write() output into a new INP instance and checking it stays the same."""
42
- for inpfile in Path(test_workspace).glob("*.inp"):
43
- inp = INP(inpfile)
44
- first_output = inp._write()
45
- inp.save("__temp.inp")
46
- second_output = INP("__temp.inp")._write()
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 os
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 os.path.join(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.iloc[0, 3] == 6
34
- assert df.iloc[-1, -1] == 21.06
35
- assert df.iloc[4, 0] == -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 = os.path.join(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
- try:
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())