floodmodeller-api 0.4.3__py3-none-any.whl → 0.4.4.post1__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 (30) hide show
  1. floodmodeller_api/_base.py +22 -37
  2. floodmodeller_api/dat.py +165 -185
  3. floodmodeller_api/ied.py +82 -87
  4. floodmodeller_api/ief.py +92 -186
  5. floodmodeller_api/inp.py +64 -70
  6. floodmodeller_api/logs/__init__.py +1 -1
  7. floodmodeller_api/logs/lf.py +61 -17
  8. floodmodeller_api/test/conftest.py +7 -0
  9. floodmodeller_api/test/test_conveyance.py +107 -0
  10. floodmodeller_api/test/test_dat.py +5 -4
  11. floodmodeller_api/test/test_data/conveyance_test.dat +165 -0
  12. floodmodeller_api/test/test_data/conveyance_test.feb +116 -0
  13. floodmodeller_api/test/test_data/conveyance_test.gxy +85 -0
  14. floodmodeller_api/test/test_data/expected_conveyance.csv +60 -0
  15. floodmodeller_api/test/test_ief.py +26 -15
  16. floodmodeller_api/test/test_logs_lf.py +54 -0
  17. floodmodeller_api/to_from_json.py +24 -12
  18. floodmodeller_api/units/boundaries.py +6 -0
  19. floodmodeller_api/units/conveyance.py +301 -0
  20. floodmodeller_api/units/sections.py +21 -0
  21. floodmodeller_api/util.py +42 -0
  22. floodmodeller_api/version.py +1 -1
  23. floodmodeller_api/xml2d.py +80 -136
  24. floodmodeller_api/zzn.py +166 -139
  25. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/METADATA +4 -1
  26. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/RECORD +30 -24
  27. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/WHEEL +1 -1
  28. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/LICENSE.txt +0 -0
  29. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/entry_points.txt +0 -0
  30. {floodmodeller_api-0.4.3.dist-info → floodmodeller_api-0.4.4.post1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,116 @@
1
+
2
+ #REVISION#1
3
+ 7 0.750 0.900 0.100 0.001 12SI
4
+ 10.000 0.010 0.010 0.700 0.100 0.700 0.000
5
+ RAD FILE
6
+
7
+ END GENERAL
8
+ RIVER
9
+ SECTION
10
+ a
11
+ 0.000 0.0001 1000
12
+ 6
13
+ 0.000 3.000 0.030 1.000 0.000 0.000
14
+ 1.000 2.500 0.030 1.000 0.000 0.000
15
+ 2.000 2.200 0.030 1.000 0.000 0.000
16
+ 3.000 1.800 0.030 1.000 0.000 0.000
17
+ 4.000 3.500 0.030 1.000 0.000 0.000
18
+ 5.000 4.000 0.030 1.000 0.000 0.000
19
+ RIVER
20
+ SECTION
21
+ a2
22
+ 0.000 0.0001 1000
23
+ 6
24
+ 0.000 3.000 0.030* 1.000 0.000 0.000
25
+ 1.000 2.500 0.030* 1.000 0.000 0.000
26
+ 2.000 2.200 0.030* 1.000 0.000 0.000
27
+ 3.000 1.800 0.030* 1.000 0.000 0.000
28
+ 4.000 3.500 0.030* 1.000 0.000 0.000
29
+ 5.000 4.000 0.030* 1.000 0.000 0.000
30
+ RIVER
31
+ SECTION
32
+ b
33
+ 0.000 0.0001 1000
34
+ 7
35
+ 0.000 3.000 0.020 1.000 0.000 0.000
36
+ 0.000 2.300 0.040 1.000 0.000 0.000
37
+ 2.000 2.200 0.015 1.000 0.000 0.000
38
+ 3.000 1.800 0.015 1.000 0.000 0.000
39
+ 3.500 2.200 0.030 1.000 0.000 0.000
40
+ 4.000 3.500 0.030 1.000 0.000 0.000
41
+ 4.000 4.000 0.030 1.000 0.000 0.000
42
+ RIVER
43
+ SECTION
44
+ b2
45
+ 0.000 0.0001 1000
46
+ 7
47
+ 0.000 3.000 0.020 1.000 0.000 0.000
48
+ 0.000 2.300 0.040 1.000 0.000 0.000
49
+ 2.000 2.200 0.015* 1.000 0.000 0.000
50
+ 3.000 1.800 0.015 1.000 0.000 0.000
51
+ 3.500 2.200 0.030 1.000 0.000 0.000
52
+ 4.000 3.500 0.030 1.000 0.000 0.000
53
+ 4.000 4.000 0.030 1.000 0.000 0.000
54
+ RIVER
55
+ SECTION
56
+ c
57
+ 0.000 0.0001 1000
58
+ 5
59
+ 0.000 4.000 0.080 1.000 0.000 0.000
60
+ 1.000 3.000 0.050 1.000 0.000 0.000
61
+ 2.000 2.000 0.015 1.000 0.000 0.000
62
+ 3.000 3.000 0.100 1.000 0.000 0.000
63
+ 4.000 4.000 0.500 1.000 0.000 0.000
64
+ RIVER
65
+ SECTION
66
+ d
67
+ 0.000 0.0001 1000
68
+ 13
69
+ 0.000 5.000 0.040 1.000 0.000 0.000
70
+ 1.000 2.000 0.040 1.000 0.000 0.000
71
+ 2.000 1.000 0.040 1.000 0.000 0.000
72
+ 3.000 0.500 0.040 1.000 0.000 0.000
73
+ 4.000 1.000 0.040 1.000 0.000 0.000
74
+ 5.000 4.000 0.100 1.000 0.000 0.000
75
+ 5.200 4.000 0.070 1.000 0.000 0.000
76
+ 6.000 1.000 0.070 1.000 0.000 0.000
77
+ 7.000 1.500 0.070 1.000 0.000 0.000
78
+ 8.000 2.000 0.070 1.000 0.000 0.000
79
+ 9.000 3.000 0.070 1.000 0.000 0.000
80
+ 10.000 4.500 0.070 1.000 0.000 0.000
81
+ 11.000 5.000 0.070 1.000 0.000 0.000
82
+ RIVER
83
+ SECTION
84
+ d2
85
+ 0.000 0.0001 1000
86
+ 13
87
+ 0.000 5.000 0.040 1.000 0.000 0.000
88
+ 1.000 2.000 0.040 1.000 0.000 0.000
89
+ 2.000 1.000 0.040 1.000 0.000 0.000
90
+ 3.000 0.500 0.040 1.000 0.000 0.000
91
+ 4.000 1.000 0.040 1.000 0.000 0.000
92
+ 5.000 4.000 0.100* 1.000 0.000 0.000
93
+ 5.200 4.000 0.070 1.000 0.000 0.000
94
+ 6.000 1.000 0.070 1.000 0.000 0.000
95
+ 7.000 1.500 0.070 1.000 0.000 0.000
96
+ 8.000 2.000 0.070 1.000 0.000 0.000
97
+ 9.000 3.000 0.070 1.000 0.000 0.000
98
+ 10.000 4.500 0.070 1.000 0.000 0.000
99
+ 11.000 5.000 0.070 1.000 0.000 0.000
100
+ INITIAL CONDITIONS
101
+ label ? flow stage froude no velocity umode ustate z
102
+ a y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
103
+ a2 y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
104
+ b y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
105
+ b2 y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
106
+ c y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
107
+ d y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
108
+ d2 y 0.000 0.000 0.000 0.000 0.000 0.000 0.000
109
+ GISINFO
110
+ RIVER SECTION a 0 0 0 0 0
111
+ RIVER SECTION a2 0 0 0 0 0
112
+ RIVER SECTION b 0 0 0 0 0
113
+ RIVER SECTION b2 0 0 0 0 0
114
+ RIVER SECTION c 0 0 0 0 0
115
+ RIVER SECTION d 0 0 0 0 0
116
+ RIVER SECTION d2 0 0 0 0 0
@@ -0,0 +1,85 @@
1
+ [RIVER_SECTION_a]
2
+ X=57008.207
3
+ Y=262998.625
4
+
5
+ [RIVER_SECTION_a2]
6
+ X=72138.8805
7
+ Y=270141.307
8
+
9
+ [RIVER_SECTION_b]
10
+ X=87269.554
11
+ Y=277283.989
12
+
13
+ [RIVER_SECTION_b2]
14
+ X=107076.983
15
+ Y=278669.505
16
+
17
+ [RIVER_SECTION_c]
18
+ X=118631.316
19
+ Y=256396.149
20
+
21
+ [RIVER_SECTION_d]
22
+ X=141189.775
23
+ Y=254195.323
24
+
25
+ [RIVER_SECTION_d2]
26
+ X=167049.472
27
+ Y=255275.736
28
+
29
+ [RIVER_SECTION_e]
30
+ X=99646.567
31
+ Y=264175.832
32
+
33
+ [RIVER_SECTION_e2]
34
+ X=99646.567
35
+ Y=264155.832
36
+
37
+ [RIVER_SECTION_e3]
38
+ X=99646.567
39
+ Y=264135.832
40
+
41
+ [VISTEXT]
42
+ VISTEXTCOUNT=0
43
+
44
+ [Font]
45
+ Font name=Segoe UI
46
+ Charset=1
47
+ Height=-12
48
+ Bold=0
49
+ Italic=0
50
+ Underline=0
51
+ Strikeout=0
52
+
53
+ [Text]
54
+ Layout=1
55
+
56
+ [Display]
57
+ MiniNodes=0
58
+ MiniStructureNodes=0
59
+ NodeLabels=0
60
+ Connections=1
61
+
62
+ [General]
63
+ UnitMove=0
64
+ ExportConnections=0
65
+ GeneralConnectionsColour=0
66
+ LateralConnectionsColour=16711680
67
+ SpillConnectionsColour=8421504
68
+
69
+ [Grid]
70
+ Show=0
71
+ X=25
72
+ Y=25
73
+
74
+ [RWC]
75
+ Top=400000
76
+ Left=-108053.691275168
77
+ Right=467462.127156744
78
+ Bottom=0
79
+
80
+ [PC]
81
+ Top=0
82
+ Left=0
83
+ Right=0
84
+ Bottom=0
85
+
@@ -0,0 +1,60 @@
1
+ a_conveyance,a_stage,a2_conveyance,a2_stage,b_conveyance,b_stage,b2_conveyance,b2_stage,c_conveyance,c_stage,d_conveyance,d_stage,d2_conveyance,d2_stage,e_conveyance,e_stage,e2_conveyance,e2_stage,e3_conveyance,e3_stage
2
+ 0,1.8,0,1.8,0,1.8,0,1.8,0,2,0,0.5,0,0.5,0,39.5,0,39.5,0,39.5
3
+ 0.005,1.84,0.005,1.84,0.013,1.84,0.013,1.84,0.003,2.038,0.039,0.583,0.039,0.583,0.069,39.55,0.069,39.55,0.066,39.55
4
+ 0.033,1.88,0.034,1.88,0.085,1.88,0.085,1.88,0.016,2.077,0.246,0.667,0.246,0.667,0.441,39.6,0.441,39.6,0.421,39.6
5
+ 0.098,1.92,0.101,1.92,0.252,1.92,0.252,1.92,0.049,2.115,0.725,0.75,0.725,0.75,1.3,39.65,1.3,39.65,1.24,39.65
6
+ 0.211,1.96,0.218,1.96,0.543,1.96,0.543,1.96,0.105,2.154,1.562,0.833,1.562,0.833,2.799,39.7,2.799,39.7,2.671,39.7
7
+ 0.383,2,0.395,2,0.984,2,0.984,2,0.19,2.192,2.832,0.917,2.832,0.917,4.953,39.75,4.953,39.75,5.292,39.75
8
+ 0.622,2.04,0.643,2.04,1.601,2.04,1.601,2.04,0.308,2.231,4.605,1,4.605,1,8.186,39.8,8.186,39.8,8.988,39.8
9
+ 0.939,2.08,0.97,2.08,2.414,2.08,2.414,2.08,0.465,2.269,4.605,1,4.605,1,13.338,39.85,13.338,39.85,14.068,39.85
10
+ 1.34,2.12,1.385,2.12,3.447,2.12,3.447,2.12,0.664,2.308,7.106,1.083,7.106,1.083,19.682,39.9,19.682,39.9,20.404,39.9
11
+ 1.835,2.16,1.896,2.16,4.719,2.16,4.719,2.16,0.909,2.346,10.067,1.167,10.067,1.167,27.24,39.95,27.24,39.95,28.002,39.95
12
+ 2.43,2.2,2.511,2.2,6.25,2.2,6.25,2.2,1.204,2.385,13.501,1.25,13.501,1.25,36.043,40,36.043,40,36.89,40
13
+ 3.16,2.243,3.454,2.243,6.25,2.2,6.25,2.2,1.552,2.423,17.424,1.333,17.424,1.333,47.444,40.053,47.444,40.053,48.142,40.053
14
+ 4.039,2.286,4.553,2.286,4.669,2.267,7.838,2.233,1.957,2.462,21.854,1.417,21.854,1.417,60.078,40.105,60.078,40.105,60.739,40.105
15
+ 5.08,2.329,5.824,2.329,5.325,2.3,9.596,2.267,2.423,2.5,26.811,1.5,26.811,1.5,73.898,40.158,73.898,40.158,74.626,40.158
16
+ 6.293,2.371,7.28,2.371,7.945,2.344,11.563,2.3,2.952,2.538,32.316,1.583,32.316,1.583,88.867,40.211,88.867,40.211,89.762,40.211
17
+ 7.69,2.414,8.934,2.414,10.935,2.388,14.585,2.344,3.549,2.577,38.39,1.667,38.39,1.667,104.955,40.263,104.955,40.263,106.113,40.263
18
+ 9.281,2.457,10.797,2.457,14.261,2.431,17.949,2.388,4.215,2.615,45.053,1.75,45.053,1.75,122.135,40.316,122.135,40.316,123.654,40.316
19
+ 11.078,2.5,12.881,2.5,17.896,2.475,21.612,2.431,4.955,2.654,52.328,1.833,52.328,1.833,140.39,40.368,140.39,40.368,142.362,40.368
20
+ 13.149,2.542,15.256,2.542,21.817,2.519,25.546,2.475,5.771,2.692,60.234,1.917,60.234,1.917,159.702,40.421,159.702,40.421,162.218,40.421
21
+ 15.403,2.583,17.858,2.583,26.005,2.562,29.729,2.519,6.666,2.731,68.792,2,68.792,2,180.058,40.474,180.058,40.474,183.208,40.474
22
+ 17.844,2.625,20.688,2.625,30.443,2.606,34.143,2.562,7.643,2.769,68.792,2,68.792,2,201.448,40.526,201.448,40.526,205.32,40.526
23
+ 20.477,2.667,23.751,2.667,35.118,2.65,38.775,2.606,8.704,2.808,78.313,2.083,78.313,2.083,223.862,40.579,223.862,40.579,228.54,40.579
24
+ 23.305,2.708,27.048,2.708,40.017,2.694,43.613,2.65,9.854,2.846,88.348,2.167,88.348,2.167,247.293,40.632,247.293,40.632,252.86,40.632
25
+ 26.331,2.75,30.583,2.75,45.13,2.737,48.647,2.694,11.094,2.885,98.893,2.25,98.893,2.25,271.736,40.684,271.736,40.684,278.273,40.684
26
+ 29.561,2.792,34.359,2.792,50.446,2.781,53.869,2.737,12.428,2.923,109.947,2.333,109.947,2.333,297.187,40.737,297.187,40.737,304.773,40.737
27
+ 32.999,2.833,38.38,2.833,55.957,2.825,59.271,2.781,13.857,2.962,121.51,2.417,121.51,2.417,323.644,40.789,323.644,40.789,332.353,40.789
28
+ 36.647,2.875,42.649,2.875,61.654,2.869,64.847,2.825,15.385,3,133.581,2.5,133.581,2.5,351.103,40.842,351.103,40.842,361.011,40.842
29
+ 40.511,2.917,47.169,2.917,67.532,2.912,70.591,2.869,15.385,3,146.163,2.583,146.163,2.583,379.563,40.895,379.563,40.895,390.741,40.895
30
+ 44.595,2.958,51.944,2.958,73.583,2.956,76.498,2.912,15.967,3.038,159.258,2.667,159.258,2.667,409.025,40.947,409.025,40.947,421.541,40.947
31
+ 48.902,3,56.978,3,79.802,3,82.563,2.956,16.643,3.077,172.868,2.75,172.868,2.75,439.488,41,439.488,41,453.41,41
32
+ 54.08,3.042,62.443,3.042,86.139,3.042,88.781,3,17.4,3.115,186.997,2.833,186.997,2.833,442.334,41.053,475.171,41.053,488.022,41.053
33
+ 59.461,3.083,68.164,3.083,92.65,3.083,94.961,3.042,18.232,3.154,201.649,2.917,201.649,2.917,449.99,41.105,512.112,41.105,523.854,41.105
34
+ 65.039,3.125,74.136,3.125,99.334,3.125,101.294,3.083,19.132,3.192,216.826,3,216.826,3,461.753,41.158,550.398,41.158,560.992,41.158
35
+ 70.812,3.167,80.354,3.167,106.185,3.167,107.779,3.125,20.097,3.231,232.612,3.083,232.612,3.083,477.158,41.211,590.1,41.211,599.507,41.211
36
+ 76.777,3.208,86.814,3.208,113.202,3.208,114.413,3.167,21.125,3.269,248.899,3.167,248.899,3.167,495.89,41.263,631.279,41.263,639.462,41.263
37
+ 82.93,3.25,93.513,3.25,120.38,3.25,121.195,3.208,22.213,3.308,265.687,3.25,265.687,3.25,517.734,41.316,673.992,41.316,680.913,41.316
38
+ 89.268,3.292,100.448,3.292,127.718,3.292,128.125,3.25,23.361,3.346,282.978,3.333,282.978,3.333,542.552,41.368,718.29,41.368,723.913,41.368
39
+ 95.789,3.333,107.615,3.333,135.212,3.333,135.199,3.292,24.567,3.385,300.776,3.417,300.776,3.417,570.251,41.421,764.222,41.421,768.512,41.421
40
+ 102.491,3.375,115.013,3.375,142.861,3.375,142.417,3.333,25.831,3.423,319.081,3.5,319.081,3.5,600.776,41.474,811.836,41.474,814.757,41.474
41
+ 109.371,3.417,122.639,3.417,150.661,3.417,149.779,3.375,27.153,3.462,337.898,3.583,337.898,3.583,634.096,41.526,861.179,41.526,862.698,41.526
42
+ 116.427,3.458,130.49,3.458,158.611,3.458,157.282,3.417,28.532,3.5,357.228,3.667,357.228,3.667,670.203,41.579,912.289,41.579,912.372,41.579
43
+ 123.658,3.5,138.565,3.5,166.708,3.5,164.925,3.458,29.969,3.538,377.075,3.75,377.075,3.75,709.103,41.632,965.212,41.632,963.827,41.632
44
+ 130.383,3.542,147.13,3.542,174.998,3.542,172.709,3.5,31.464,3.577,397.441,3.833,397.441,3.833,750.809,41.684,1019.986,41.684,1017.102,41.684
45
+ 137.342,3.583,155.931,3.583,183.399,3.583,180.715,3.542,33.017,3.615,418.329,3.917,418.329,3.917,795.35,41.737,1076.653,41.737,1072.241,41.737
46
+ 144.538,3.625,164.977,3.625,191.907,3.625,188.817,3.583,34.628,3.654,439.744,4,439.744,4,842.762,41.789,1135.253,41.789,1129.283,41.789
47
+ 151.975,3.667,174.274,3.667,200.519,3.667,197.014,3.625,36.298,3.692,439.744,4,439.744,4,893.079,41.842,1195.824,41.842,1188.267,41.842
48
+ 159.657,3.708,183.827,3.708,209.231,3.708,205.302,3.667,38.027,3.731,426.312,4.167,461.827,4.083,946.341,41.895,1258.402,41.895,1249.232,41.895
49
+ 167.586,3.75,193.642,3.75,218.041,3.75,213.681,3.708,39.816,3.769,450.518,4.25,487.595,4.167,1002.596,41.947,1323.025,41.947,1312.216,41.947
50
+ 175.766,3.792,203.721,3.792,226.946,3.792,222.15,3.75,41.665,3.808,475.304,4.333,513.966,4.25,1061.897,42,1389.731,42,1377.258,42
51
+ 184.201,3.833,214.071,3.833,235.943,3.833,230.707,3.792,43.575,3.846,500.669,4.417,540.939,4.333,1121.642,42.05,1457.364,42.05,1443.44,42.05
52
+ 192.892,3.875,224.695,3.875,245.03,3.875,239.35,3.833,45.546,3.885,526.611,4.5,568.512,4.417,1184.196,42.1,1527.027,42.1,1511.628,42.1
53
+ 201.844,3.917,235.596,3.917,254.203,3.917,248.079,3.875,47.58,3.923,550.867,4.583,596.684,4.5,1249.604,42.15,1598.754,42.15,1581.853,42.15
54
+ 211.059,3.958,246.779,3.958,263.461,3.958,256.892,3.917,49.675,3.962,575.889,4.667,624.458,4.583,1317.908,42.2,1672.564,42.2,1654.136,42.2
55
+ 220.542,4,258.247,4,272.801,4,265.789,3.958,51.833,4,601.69,4.75,652.996,4.667,,,,,,
56
+ ,,,,,,274.768,4,51.833,4,628.277,4.833,682.307,4.75,,,,,,
57
+ ,,,,,,,,,,655.662,4.917,712.398,4.833,,,,,,
58
+ ,,,,,,,,,,683.856,5,743.277,4.917,,,,,,
59
+ ,,,,,,,,,,683.856,5,774.952,5,,,,,,
60
+ ,,,,,,,,,,,,774.952,5,,,,,,
@@ -4,6 +4,7 @@ from unittest.mock import call, patch
4
4
  import pytest
5
5
 
6
6
  from floodmodeller_api import IEF
7
+ from floodmodeller_api.util import FloodModellerAPIError
7
8
 
8
9
 
9
10
  @pytest.fixture()
@@ -30,11 +31,24 @@ def exe_bin(tmpdir) -> Path:
30
31
  return Path(tmpdir)
31
32
 
32
33
 
34
+ @pytest.fixture()
35
+ def p_open():
36
+ with patch("floodmodeller_api.ief.Popen") as p_open:
37
+ yield p_open
38
+
39
+
40
+ @pytest.fixture()
41
+ def sleep():
42
+ with patch("floodmodeller_api.ief.time.sleep") as sleep:
43
+ yield sleep
44
+
45
+
33
46
  def test_ief_open_does_not_change_data(ief: IEF, data_before: str):
34
47
  """IEF: Test str representation equal to ief file with no changes"""
35
48
  assert ief._write() == data_before
36
49
 
37
50
 
51
+ @pytest.mark.usefixtures("log_timeout")
38
52
  @pytest.mark.parametrize(
39
53
  ("precision", "method", "amend", "exe"),
40
54
  [
@@ -56,6 +70,8 @@ def test_simulate(
56
70
  ief: IEF,
57
71
  ief_fp: Path,
58
72
  exe_bin: Path,
73
+ p_open,
74
+ sleep,
59
75
  precision: str,
60
76
  method: str,
61
77
  amend: bool,
@@ -64,21 +80,16 @@ def test_simulate(
64
80
  if amend:
65
81
  ief.launchdoubleprecisionversion = 1
66
82
 
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]
83
+ p_open.return_value.poll.side_effect = [None, None, 0]
73
84
 
74
- exe_path = Path(exe_bin, exe)
75
- ief.simulate(method=method, precision=precision, enginespath=str(exe_bin))
85
+ exe_path = Path(exe_bin, exe)
86
+ ief.simulate(method=method, precision=precision, enginespath=str(exe_bin))
76
87
 
77
- p_open.assert_called_once_with(f'"{exe_path}" -sd "{ief_fp}"', cwd=str(ief_fp.parent))
88
+ p_open.assert_called_once_with(f'"{exe_path}" -sd "{ief_fp}"', cwd=str(ief_fp.parent))
78
89
 
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)]
90
+ if method == "WAIT":
91
+ assert p_open.return_value.poll.call_count == 3
92
+ assert sleep.call_args_list[-3:] == [call(0.1), call(1), call(1)]
82
93
 
83
94
 
84
95
  def test_simulate_error_without_bin(tmpdir, ief: IEF):
@@ -91,7 +102,7 @@ def test_simulate_error_without_bin(tmpdir, ief: IEF):
91
102
  r"\n"
92
103
  r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
93
104
  )
94
- with pytest.raises(Exception, match=msg):
105
+ with pytest.raises(FloodModellerAPIError, match=msg):
95
106
  ief.simulate(enginespath=str(Path(tmpdir, "bin")))
96
107
 
97
108
 
@@ -105,7 +116,7 @@ def test_simulate_error_without_exe(tmpdir, ief: IEF):
105
116
  r"\n"
106
117
  r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
107
118
  )
108
- with pytest.raises(Exception, match=msg):
119
+ with pytest.raises(FloodModellerAPIError, match=msg):
109
120
  ief.simulate(enginespath=str(tmpdir))
110
121
 
111
122
 
@@ -121,5 +132,5 @@ def test_simulate_error_without_save():
121
132
  r"\n"
122
133
  r"\nFor additional support, go to: https://github\.com/People-Places-Solutions/floodmodeller-api"
123
134
  )
124
- with pytest.raises(Exception, match=msg):
135
+ with pytest.raises(FloodModellerAPIError, match=msg):
125
136
  ief.simulate()
@@ -1,9 +1,12 @@
1
1
  from pathlib import Path
2
+ from unittest.mock import MagicMock, patch
2
3
 
3
4
  import pandas as pd
4
5
  import pytest
6
+ from freezegun import freeze_time
5
7
 
6
8
  from floodmodeller_api import IEF, LF1
9
+ from floodmodeller_api.logs import create_lf
7
10
 
8
11
 
9
12
  @pytest.fixture
@@ -46,3 +49,54 @@ def test_lf1_from_ief(lf1_fp, test_workspace):
46
49
  assert lf1._filepath == lf1_from_ief._filepath
47
50
  assert lf1.info == lf1_from_ief.info
48
51
  pd.testing.assert_frame_equal(lf1.to_dataframe(), lf1_from_ief.to_dataframe())
52
+
53
+
54
+ def test_log_file_unsupported(capsys):
55
+ lf = create_lf(None, "lf3")
56
+
57
+ assert lf is None
58
+ assert (
59
+ capsys.readouterr().out
60
+ == "No progress bar as log file must have suffix lf1 or lf2. Simulation will continue as usual.\n"
61
+ )
62
+
63
+
64
+ @pytest.mark.usefixtures("log_timeout")
65
+ def test_log_file_timeout(capsys):
66
+ lf_filepath = MagicMock()
67
+ lf_filepath.is_file.return_value = False
68
+ lf = create_lf(lf_filepath, "lf1")
69
+
70
+ assert lf is None
71
+ assert (
72
+ capsys.readouterr().out
73
+ == "No progress bar as log file is expected but not detected. Simulation will continue as usual.\n"
74
+ )
75
+
76
+
77
+ @pytest.mark.usefixtures("log_timeout")
78
+ @freeze_time("1970-01-01 00:00:00", tick=True)
79
+ def test_log_file_from_old_run(capsys):
80
+ lf_filepath = MagicMock()
81
+ lf_filepath.is_file.return_value = True
82
+ lf_filepath.stat.return_value.st_mtime = -10
83
+ lf = create_lf(lf_filepath, "lf1")
84
+
85
+ assert lf is None
86
+ assert (
87
+ capsys.readouterr().out
88
+ == "No progress bar as log file is from previous run. Simulation will continue as usual.\n"
89
+ )
90
+
91
+
92
+ @pytest.mark.usefixtures("log_timeout")
93
+ @freeze_time("1970-01-01 00:00:00", tick=True)
94
+ def test_log_file_found():
95
+ lf_filepath = MagicMock()
96
+ lf_filepath.is_file.return_value = True
97
+ lf_filepath.stat.return_value.st_mtime = -1
98
+ with patch("floodmodeller_api.logs.lf.LF1") as lf1:
99
+ lf = create_lf(lf_filepath, "lf1")
100
+
101
+ assert lf is not None
102
+ lf1.assert_called_once_with(lf_filepath)
@@ -14,9 +14,11 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import json
18
20
  from pathlib import Path
19
- from typing import Any, Union
21
+ from typing import Any
20
22
 
21
23
  import pandas as pd
22
24
  from pandas import Index
@@ -45,6 +47,23 @@ def is_jsonable(obj: Any) -> bool:
45
47
  return False
46
48
 
47
49
 
50
+ def pandas_to_json(obj: pd.DataFrame | pd.Series) -> dict:
51
+ if isinstance(obj, pd.DataFrame):
52
+ if isinstance(obj.columns, pd.MultiIndex):
53
+ # Handle multi index columns (i.e. ZZN dataframe results)
54
+ obj.columns = pd.Index(map(str, obj.columns.values))
55
+
56
+ return {"class": "pandas.DataFrame", "object": obj.to_dict()}
57
+
58
+ # otherwise returns as series
59
+ return {
60
+ "class": "pandas.Series",
61
+ "variable_name": obj.name,
62
+ "index_name": obj.index.name,
63
+ "object": obj.to_dict(),
64
+ }
65
+
66
+
48
67
  def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0911
49
68
  """
50
69
  Function to undertake a recursion through the different elements of the python object
@@ -65,15 +84,8 @@ def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0
65
84
  if is_jsonable(obj):
66
85
  return obj
67
86
 
68
- if isinstance(obj, pd.DataFrame):
69
- return {"class": "pandas.DataFrame", "object": obj.to_dict()}
70
- if isinstance(obj, pd.Series):
71
- return {
72
- "class": "pandas.Series",
73
- "variable_name": obj.name,
74
- "index_name": obj.index.name,
75
- "object": obj.to_dict(),
76
- }
87
+ if isinstance(obj, (pd.DataFrame, pd.Series)):
88
+ return pandas_to_json(obj)
77
89
 
78
90
  # To convert WindowsPath, no serializable, objects to string, serializable.
79
91
  if isinstance(obj, Path):
@@ -107,7 +119,7 @@ def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0
107
119
  return return_dict
108
120
 
109
121
 
110
- def from_json(obj: Union[str, dict]) -> dict:
122
+ def from_json(obj: str | dict) -> dict:
111
123
  """
112
124
  Function to convert a JSON string back into Python objects
113
125
 
@@ -126,7 +138,7 @@ def from_json(obj: Union[str, dict]) -> dict:
126
138
  return recursive_from_json(obj_dict)
127
139
 
128
140
 
129
- def recursive_from_json(obj: Union[dict, Any]) -> Any:
141
+ def recursive_from_json(obj: dict | Any) -> Any:
130
142
  """
131
143
  Function to undertake a recursion through the different elements of the JSON object
132
144
 
@@ -17,6 +17,7 @@ address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London
17
17
  import pandas as pd
18
18
 
19
19
  from floodmodeller_api.validation import _validate_unit
20
+ from floodmodeller_api.validation.parameters import parameter_options
20
21
 
21
22
  from ._base import Unit
22
23
  from .helpers import (
@@ -212,6 +213,11 @@ class HTBDY(Unit):
212
213
  self.data = self.data.set_index("Time")
213
214
  self.data = self.data["Stage"] # Convert to series
214
215
 
216
+ # Fix legacy Flood Modeller bug where timeunit is present in extendmethod place
217
+ if self.extendmethod in parameter_options["timeunit"]["options"][1]:
218
+ self.timeunit = self.extendmethod
219
+ self.extendmethod = "EXTEND"
220
+
215
221
  def _write(self):
216
222
  """Function to write a valid HTBDY block"""
217
223
  _validate_unit(self) # Function to check the params are valid for HTBDY