diff --git a/.gitignore b/.gitignore index 58a72e8..c658b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ target/ .pytest_cache/ epanet_python/toolkit/tests/data/test.* epanet_python/toolkit/tests/data/test_reopen.inp +epanet_python/toolkit/tests/data/test_warnings.rpt # Wrapped libraries *.h diff --git a/before_build.bat b/before_build.bat index 0babcaa..ff99b86 100644 --- a/before_build.bat +++ b/before_build.bat @@ -7,13 +7,14 @@ :: US EPA - ORD/NRMRL :: :: Requires: +:: git :: CMake -:: Visual Studio 2015 +:: Visual Studio Build Tools :: SWIG :: :: Note: :: This script must be located at the root of the project folder -: in order to work correctly. +:: in order to work correctly. :: diff --git a/epanet_python/output/setup.py b/epanet_python/output/setup.py index 6e38ef7..05fa028 100644 --- a/epanet_python/output/setup.py +++ b/epanet_python/output/setup.py @@ -13,12 +13,13 @@ # Python packages: numpy # -try: - from setuptools import setup, Extension - from setuptools.command.build_ext import build_ext -except ImportError: - from distutils.core import setup, Extension - from distutils.command.build_ext import build_ext +#try: +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext + +#except ImportError: +# from distutils.core import setup, Extension +# from distutils.command.build_ext import build_ext microlib_name = 'epanet.output' diff --git a/epanet_python/output/tests/test_output.py b/epanet_python/output/tests/test_output.py index 96446c6..5659f84 100644 --- a/epanet_python/output/tests/test_output.py +++ b/epanet_python/output/tests/test_output.py @@ -51,6 +51,16 @@ def test_outputmetadata_handle(handle): assert temp == ref[attr] +def test_getnetsize(handle): + # node, tank, link, pump, valve + ref_array = np.array([11, 2, 13, 1, 0]) + + netsize_list = oapi.getnetsize(handle) + assert len(netsize_list) == 5 + + assert np.array_equal(netsize_list, ref_array) + + def test_getnodeSeries(handle): ref_array = np.array( diff --git a/epanet_python/toolkit/epanet/toolkit/toolkit.i b/epanet_python/toolkit/epanet/toolkit/toolkit.i index 28115c4..814b061 100644 --- a/epanet_python/toolkit/epanet/toolkit/toolkit.i +++ b/epanet_python/toolkit/epanet/toolkit/toolkit.i @@ -97,17 +97,25 @@ and return a (possibly) different pointer */ /* INSERTS CUSTOM EXCEPTION HANDLING IN WRAPPER */ %exception { + int err_code; char* err_msg; err_clear(arg1); $function - if (err_check(arg1, &err_msg)) + + err_code = err_check(arg1, &err_msg); + if ( err_code > 10) { PyErr_SetString(PyExc_Exception, err_msg); toolkit_free((void **)&err_msg); SWIG_fail; } + else if (err_code > 0) + { + PyErr_WarnEx(PyExc_Warning, err_msg, 2); + toolkit_free((void **)&err_msg); + } } @@ -116,6 +124,9 @@ and return a (possibly) different pointer */ int proj_run(Handle ph, const char *input_path, const char *report_path, const char *output_path); int proj_init(Handle ph, const char *rptFile, const char *outFile, EN_FlowUnits unitsType, EN_HeadLossType headLossType); int proj_open(Handle ph, const char *inpFile, const char *rptFile, const char *binOutFile); +//int proj_gettitle(Handle ph, char *line1, char *line2, char *line3); +//int proj_settitle(Handle ph, const char *line1, const char *line2, const char *line3); +int proj_getcount(Handle ph, EN_CountType code, int *OUTPUT); int proj_savefile(Handle ph, const char *filename); int proj_close(Handle ph); @@ -145,7 +156,6 @@ int rprt_writeresults(Handle ph); int rprt_reset(Handle ph); int rprt_set(Handle ph, char *reportCommand); int rprt_setlevel(Handle ph, EN_StatusReport code); -int rprt_getcount(Handle ph, EN_CountType code, int *OUTPUT); int rprt_anlysstats(Handle ph, EN_AnalysisStatistic code, double *OUTPUT ); diff --git a/epanet_python/toolkit/tests/data/test_warnings.inp b/epanet_python/toolkit/tests/data/test_warnings.inp new file mode 100644 index 0000000..0a1dded --- /dev/null +++ b/epanet_python/toolkit/tests/data/test_warnings.inp @@ -0,0 +1,178 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 750 ; + 12 700 750 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + +[RESERVOIRS] +;ID Head Pattern + 9 800 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + 2 850 120 100 150 50.5 0 ; + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 10 10 11 10530 18 100 0 Open ; + 11 11 12 5280 14 100 0 Open ; + 12 12 13 5280 10 100 0 Open ; + 21 21 22 5280 10 100 0 Open ; + 22 22 23 5280 12 100 0 Open ; + 31 31 32 5280 6 100 0 Open ; + 110 2 12 200 18 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + 9 9 10 HEAD 1 ; + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + 1 1.0 1.2 1.4 1.6 1.4 1.2 + 1 1.0 0.8 0.6 0.4 0.6 0.8 + +[CURVES] +;ID X-Value Y-Value +;PUMP: Pump Curve for Pump 9 + 1 1500 250 + +[CONTROLS] + LINK 9 OPEN IF NODE 2 BELOW 110 + LINK 9 CLOSED IF NODE 2 ABOVE 140 + + +[RULES] + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + 10 0.5 + 11 0.5 + 12 0.5 + 13 0.5 + 21 0.5 + 22 0.5 + 23 0.5 + 31 0.5 + 32 0.5 + 9 1.0 + 2 1.0 + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 24:00 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic None + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 9 10.00 70.00 + 2 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/epanet_python/toolkit/tests/test_toolkit.py b/epanet_python/toolkit/tests/test_toolkit.py index 627118c..48fc7a1 100644 --- a/epanet_python/toolkit/tests/test_toolkit.py +++ b/epanet_python/toolkit/tests/test_toolkit.py @@ -91,7 +91,7 @@ def test_hyd_step(handle): step = en.hydr_next(handle) - if time == 0.: + if not step > 0.: break en.hydr_close(handle) @@ -109,7 +109,7 @@ def test_qual_step(handle): step = en.qual_next(handle) - if time == 0.: + if not step > 0.: break en.qual_close(handle) @@ -117,7 +117,7 @@ def test_qual_step(handle): def test_report(handle): - nlinks = en.rprt_getcount(handle, en.CountType.LINKS) + nlinks = en.proj_getcount(handle, en.CountType.LINKS) assert nlinks == 13 en.hydr_solve(handle) @@ -251,3 +251,55 @@ def test_simplecontrol(handle): value.clear() value = en.scntl_get(handle, 2) assert value == [1, 13, 0.0, 11, 140.0] + + +WARNING_TEST_INP = os.path.join(DATA_PATH, 'test_warnings.inp') +WARNING_TEST_RPT = os.path.join(DATA_PATH, 'test_warnings.rpt') +WARNING_TEST_OUT = os.path.join(DATA_PATH, 'test_warnings.out') + +@pytest.fixture() +def handle_warn(request): + _handle = en.proj_create() + en.proj_open(_handle, WARNING_TEST_INP, WARNING_TEST_RPT, WARNING_TEST_OUT) + + def close(): + en.proj_close(_handle) + en.proj_delete(_handle) + + request.addfinalizer(close) + return _handle + + +import warnings +warnings.simplefilter("default") + +def test_hyd_warning(handle_warn): + with pytest.warns(Warning): + en.hydr_open(handle_warn) + en.hydr_init(handle_warn, en.SaveOption.NOSAVE) + + while True: + time = en.hydr_run(handle_warn) + + step = en.hydr_next(handle_warn) + + if not step > 0.: + break + + en.hydr_close(handle_warn) + + +def test_exception(handle_warn): + with pytest.raises(Exception): + #en.hydr_open(handle_warn) + en.hydr_init(handle_warn, en.SaveOption.NOSAVE) + + while True: + time = en.hydr_run(handle_warn) + + step = en.hydr_next(handle_warn) + + if not step > 0.: + break + + en.hydr_close(handle_warn)