From d92cbb5b9420f45430eda0fb686ace5d14b1a25c Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Tue, 4 Sep 2018 15:34:27 -0400 Subject: [PATCH 1/2] Adding WITH_GENX --- toolkit/requirements.txt | 2 -- toolkit/setup.py | 7 ++++--- 2 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 toolkit/requirements.txt diff --git a/toolkit/requirements.txt b/toolkit/requirements.txt deleted file mode 100644 index af9d7f74..00000000 --- a/toolkit/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ - --e ./ diff --git a/toolkit/setup.py b/toolkit/setup.py index 0b8c038c..9aa25863 100644 --- a/toolkit/setup.py +++ b/toolkit/setup.py @@ -26,11 +26,12 @@ ext_modules = [ Extension('swmm.toolkit._toolkit', - include_dirs = ['swmm/toolkit/'], - libraries = ['swmm5'], - library_dirs = ['swmm/toolkit/'], sources = ['swmm/toolkit/toolkit.i'], swig_opts=['-py3'], + include_dirs = ['swmm/toolkit/'], + library_dirs = ['swmm/toolkit/'], + libraries = ['swmm5'], + extra_compile_args = ["/D WITH_GENX"], language = 'C' ) ], From c1c309604d6c019a5f2bde55f6f2394227a24fd5 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 21 Dec 2018 12:34:29 -0500 Subject: [PATCH 2/2] Reorganizing package layout --- .gitignore | 3 + before_build.bat | 34 +++++ output/tests/data/__init__.py | 14 -- setup.py | 72 +++++++++ .../output}/requirements.txt | 2 + {output => swmm_python/output}/setup.py | 17 ++- .../output}/swmm/output/__init__.py | 0 .../output}/swmm/output/output.i | 0 .../output}/tests/data/Example1.out | Bin .../output}/tests/test_output.py | 143 +++++++++--------- {toolkit => swmm_python/toolkit}/setup.py | 18 ++- .../toolkit}/swmm/toolkit/__init__.py | 0 .../toolkit}/swmm/toolkit/toolkit.i | 0 .../toolkit}/tests/data/Example1.inp | 0 .../toolkit}/tests/test_toolkit.py | 37 ++--- toolkit/tests/data/__init__.py | 10 -- tox.ini | 16 ++ 17 files changed, 239 insertions(+), 127 deletions(-) create mode 100644 before_build.bat delete mode 100644 output/tests/data/__init__.py create mode 100644 setup.py rename {output => swmm_python/output}/requirements.txt (53%) rename {output => swmm_python/output}/setup.py (75%) rename {output => swmm_python/output}/swmm/output/__init__.py (100%) rename {output => swmm_python/output}/swmm/output/output.i (100%) rename {output => swmm_python/output}/tests/data/Example1.out (100%) rename {output => swmm_python/output}/tests/test_output.py (84%) rename {toolkit => swmm_python/toolkit}/setup.py (71%) rename {toolkit => swmm_python/toolkit}/swmm/toolkit/__init__.py (100%) rename {toolkit => swmm_python/toolkit}/swmm/toolkit/toolkit.i (100%) rename {toolkit => swmm_python/toolkit}/tests/data/Example1.inp (100%) rename {toolkit => swmm_python/toolkit}/tests/test_toolkit.py (75%) delete mode 100644 toolkit/tests/data/__init__.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 2bfb76ba..7813fc1a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.exp *.so *.h +buildlib/ build/ dist/ @@ -23,3 +24,5 @@ output_wrap.c toolkit.py toolkit_wrap.c + +swmm_python/toolkit/tests/data/test.* diff --git a/before_build.bat b/before_build.bat new file mode 100644 index 00000000..030153a5 --- /dev/null +++ b/before_build.bat @@ -0,0 +1,34 @@ +:: +:: before_build.bat - Prepares for swmm toolkit and output module builds +:: +:: Date Created: 12/21/2018 +:: +:: Author: Michael E. Tryby +:: US EPA - ORD/NRMRL +:: + +set PROJECT_PATH=%~1 + +set TOOLKIT_PATH=\swmm_python\toolkit\swmm\toolkit +set OUTPUT_PATH=\swmm_python\output\swmm\output + + +mkdir buildlib +cd buildlib +git clone --branch=feature-wrapper https://github.com/michaeltryby/Stormwater-Management-Model.git swmm +cd swmm + + +mkdir buildprod +cd buildprod +cmake -G"Visual Studio 14 2015 Win64" -DBUILD_TESTS=0 .. +cmake --build . --config Release + + +copy /Y .\bin\Release\swmm5.dll %PROJECT_PATH%\%TOOLKIT_PATH% +copy /Y .\lib\Release\swmm5.lib %PROJECT_PATH%\%TOOLKIT_PATH% +copy /Y ..\include\*.h %PROJECT_PATH%\%TOOLKIT_PATH% + +copy /Y .\bin\Release\swmm-output.dll %PROJECT_PATH%\%OUTPUT_PATH% +copy /Y .\lib\Release\swmm-output.lib %PROJECT_PATH%\%OUTPUT_PATH% +copy /Y ..\tools\swmm-output\include\*.h %PROJECT_PATH%\%OUTPUT_PATH% diff --git a/output/tests/data/__init__.py b/output/tests/data/__init__.py deleted file mode 100644 index 89ab8ab8..00000000 --- a/output/tests/data/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -# __init__.py -# -# Created: 8/7/2018 -# Author: Michael E. Tryby -# US EPA - ORD/NRMRL -# - -import os - -DATA_PATH = os.path.abspath(os.path.dirname(__file__)) - -OUTPUT_FILE_EXAMPLE1 = os.path.join(DATA_PATH, 'Example1.out') diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..3e00c3d7 --- /dev/null +++ b/setup.py @@ -0,0 +1,72 @@ + + +import os +import pathlib + +from six import iteritems + +from setuptools import setup +from setuptools.command.develop import develop +from setuptools.command.install import install + + +import sys +import subprocess + + +PACKAGE_NAME = 'swmm' +SOURCES = { + 'swmm.toolkit': 'swmm_python/toolkit', + 'swmm.output': 'swmm_python/output' +} + + +def install_microlibs(sources, develop=False): + """ Use pip to install all microlibraries. """ + print("installing all microlibs in {} mode".format( + "development" if develop else "normal")) + wd = pathlib.Path.cwd() + for k, v in iteritems(sources): + try: + microlib_dir = os.fspath(wd.joinpath(v)) + if develop: + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-e', '.'], cwd=microlib_dir) + else: + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '.'], cwd=microlib_dir) + except Exception as e: + print("Oops, something went wrong installing", k, microlib_dir) + print(e) + finally: + os.chdir(wd) + + +class DevelopCmd(develop): + """ Add custom steps for the develop command """ + def run(self): + install_microlibs(SOURCES, develop=True) + develop.run(self) + + +class InstallCmd(install): + """ Add custom steps for the install command """ + def run(self): + install_microlibs(SOURCES, develop=False) + install.run(self) + + +setup( + name=PACKAGE_NAME, + version="0.2.0a", + author="Michael Tryby", + author_email="Michael Tryby@epa.gov", + description="swmm_python - SWIG generated python wrappers for swmm libraries", + license="CC0", + classifiers=[ + 'Private :: Do Not Upload to pypi server', + ], + cmdclass={ + 'install': InstallCmd, + 'develop': DevelopCmd + + } +) diff --git a/output/requirements.txt b/swmm_python/output/requirements.txt similarity index 53% rename from output/requirements.txt rename to swmm_python/output/requirements.txt index c72a5d98..07eb1f6c 100644 --- a/output/requirements.txt +++ b/swmm_python/output/requirements.txt @@ -1,3 +1,5 @@ +aenum + -e ./ diff --git a/output/setup.py b/swmm_python/output/setup.py similarity index 75% rename from output/setup.py rename to swmm_python/output/setup.py index 5d269743..66eff1fa 100644 --- a/output/setup.py +++ b/swmm_python/output/setup.py @@ -2,13 +2,13 @@ # # setup.py - Setup script for swmm_output python extension -# +# # Created: 7/2/2018 # Author: Michael E. Tryby # US EPA - ORD/NRMRL # # Requires: -# Platform C language compiler +# Platform C language compiler # SWIG # @@ -20,12 +20,14 @@ from distutils.command.build_ext import build_ext +microlib_name = 'swmm.output' + setup( - name = "swmm-output", + name = microlib_name, version = "0.3.0-dev", ext_modules = [ - Extension("swmm.output._output", + Extension("swmm.output._output", include_dirs = ['swmm/output/'], libraries = ['swmm-output'], library_dirs = ['swmm/output/'], @@ -34,10 +36,11 @@ language='C' ) ], - packages = ['swmm.output'], + namespace_packages=['swmm'], + packages = [microlib_name], py_modules = ['output'], - package_data = {'swmm.output':['*swmm-output.dll', '*swmm-output.so']}, - + package_data = {microlib_name:['*swmm-output.dll', '*swmm-output.so']}, + install_requires = [ 'aenum' ] diff --git a/output/swmm/output/__init__.py b/swmm_python/output/swmm/output/__init__.py similarity index 100% rename from output/swmm/output/__init__.py rename to swmm_python/output/swmm/output/__init__.py diff --git a/output/swmm/output/output.i b/swmm_python/output/swmm/output/output.i similarity index 100% rename from output/swmm/output/output.i rename to swmm_python/output/swmm/output/output.i diff --git a/output/tests/data/Example1.out b/swmm_python/output/tests/data/Example1.out similarity index 100% rename from output/tests/data/Example1.out rename to swmm_python/output/tests/data/Example1.out diff --git a/output/tests/test_output.py b/swmm_python/output/tests/test_output.py similarity index 84% rename from output/tests/test_output.py rename to swmm_python/output/tests/test_output.py index eebb2e91..f8cfd936 100644 --- a/output/tests/test_output.py +++ b/swmm_python/output/tests/test_output.py @@ -7,6 +7,7 @@ # # Unit testing for SWMM Output API using pytest. # +import os import pytest import numpy as np @@ -14,7 +15,8 @@ from swmm.output import OutputMetadata from swmm.output import output as smo -from data import OUTPUT_FILE_EXAMPLE1 +DATA_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') +OUTPUT_FILE_EXAMPLE1 = os.path.join(DATA_PATH, 'Example1.out') def test_openclose(): @@ -22,23 +24,23 @@ def test_openclose(): smo.open(_handle, OUTPUT_FILE_EXAMPLE1) smo.close(_handle) - + @pytest.fixture() -def handle(request): +def handle(request): _handle = smo.init() smo.open(_handle, OUTPUT_FILE_EXAMPLE1) - + def close(): smo.close(_handle) - - request.addfinalizer(close) - return _handle + + request.addfinalizer(close) + return _handle def test_outputmetadata(handle): - + om = OutputMetadata(handle) - + ref = { smo.SubcatchAttribute.RAINFALL: ("Rainfall", "in/hr"), smo.SubcatchAttribute.SNOW_DEPTH: ("Snow Depth", "in"), @@ -50,7 +52,7 @@ def test_outputmetadata(handle): smo.SubcatchAttribute.SOIL_MOISTURE: ("Soil Moisture", "%"), smo.SubcatchAttribute.POLLUT_CONC_0: ("TSS", "mg/L"), smo.SubcatchAttribute.POLLUT_CONC_1: ("Lead", "ug/L"), - + smo.NodeAttribute.INVERT_DEPTH: ("Invert Depth", "ft"), smo.NodeAttribute.HYDRAULIC_HEAD: ("Hydraulic Head", "ft"), smo.NodeAttribute.PONDED_VOLUME: ("Ponded Volume", "cu ft"), @@ -59,7 +61,7 @@ def test_outputmetadata(handle): smo.NodeAttribute.FLOODING_LOSSES: ("Flooding Loss", "cu ft/sec"), smo.NodeAttribute.POLLUT_CONC_0: ("TSS", "mg/L"), smo.NodeAttribute.POLLUT_CONC_1: ("Lead", "ug/L"), - + smo.LinkAttribute.FLOW_RATE: ("Flow Rate", "cu ft/sec"), smo.LinkAttribute.FLOW_DEPTH: ("Flow Depth", "ft"), smo.LinkAttribute.FLOW_VELOCITY: ("Flow Velocity", "ft/sec"), @@ -67,7 +69,7 @@ def test_outputmetadata(handle): smo.LinkAttribute.CAPACITY: ("Capacity", "%"), smo.LinkAttribute.POLLUT_CONC_0: ("TSS", "mg/L"), smo.LinkAttribute.POLLUT_CONC_1: ("Lead", "ug/L"), - + smo.SystemAttribute.AIR_TEMP: ("Temperature", "deg F"), smo.SystemAttribute.RAINFALL: ("Rainfall", "in/hr"), smo.SystemAttribute.SNOW_DEPTH: ("Snow Depth", "in"), @@ -81,113 +83,113 @@ def test_outputmetadata(handle): smo.SystemAttribute.FLOOD_LOSSES: ("Flood Losses", "cu ft/sec"), smo.SystemAttribute.OUTFALL_FLOWS: ("Outfall Flow", "cu ft/sec"), smo.SystemAttribute.VOLUME_STORED: ("Volume Stored", "cu ft"), - smo.SystemAttribute.EVAP_RATE: ("Evaporation Rate", "in/day") + smo.SystemAttribute.EVAP_RATE: ("Evaporation Rate", "in/day") } - + for attr in smo.SubcatchAttribute: temp = om.get_attribute_metadata(attr) - assert temp == ref[attr] - + assert temp == ref[attr] + for attr in smo.NodeAttribute: temp = om.get_attribute_metadata(attr) - assert temp == ref[attr] - + assert temp == ref[attr] + for attr in smo.LinkAttribute: temp = om.get_attribute_metadata(attr) - assert temp == ref[attr] - + assert temp == ref[attr] + for attr in smo.SystemAttribute: temp = om.get_attribute_metadata(attr) - assert temp == ref[attr] - - + assert temp == ref[attr] + + def test_getversion(handle): - + assert smo.getversion(handle) == 51000 def test_getprojectsize(handle): - + assert smo.getprojectsize(handle) == [8, 14, 13, 2] def test_getpollutantunits(handle): - + assert smo.getunits(handle)[2:] == [0, 1] - + def test_getstartdate(handle): - + assert smo.getstartdate(handle) == 35796 - + def test_gettimes(handle): - + assert smo.gettimes(handle, smo.Time.NUM_PERIODS) == 36 def test_getelementname(handle): - + assert smo.getelementname(handle, smo.ElementType.NODE, 1) == "10" - + def test_getsubcatchseries(handle): - - ref_array = np.array([0.0, - 1.2438242, - 2.5639679, - 4.524055, - 2.5115132, - 0.69808137, - 0.040894926, - 0.011605669, - 0.00509294, + + ref_array = np.array([0.0, + 1.2438242, + 2.5639679, + 4.524055, + 2.5115132, + 0.69808137, + 0.040894926, + 0.011605669, + 0.00509294, 0.0027438672]) - - test_array = smo.getsubcatchseries(handle, 1, smo.SubcatchAttribute.RUNOFF_RATE, 0, 10) - - assert len(test_array) == 10 + + test_array = smo.getsubcatchseries(handle, 1, smo.SubcatchAttribute.RUNOFF_RATE, 0, 10) + + assert len(test_array) == 10 assert np.allclose(test_array, ref_array) - + def test_getsubcatchattribute(handle): - + ref_array = np.array([0.125, 0.125, 0.125, 0.125, 0.125, 0.225, - 0.225, + 0.225, 0.225]) - + test_array = smo.getsubcatchattribute(handle, 1, smo.SubcatchAttribute.INFIL_LOSS) assert len(test_array) == 8 assert np.allclose(test_array, ref_array) - + def test_getsubcatchresult(handle): - - ref_array = np.array([0.5, - 0.0, - 0.0, - 0.125, - 1.2438242, - 0.0, - 0.0, - 0.0, - 33.481991, + + ref_array = np.array([0.5, + 0.0, + 0.0, + 0.125, + 1.2438242, + 0.0, + 0.0, + 0.0, + 33.481991, 6.6963983]) - + test_array = smo.getsubcatchresult(handle, 1, 1) - + assert len(test_array) == 10 assert np.allclose(test_array, ref_array) def test_getnoderesult(handle): - + ref_array = np.array([0.296234, 995.296204, 0.0, @@ -198,13 +200,13 @@ def test_getnoderesult(handle): 3.072293]) test_array = smo.getnoderesult(handle, 2, 2) - + assert len(test_array) == 8 assert np.allclose(test_array, ref_array) - + def test_getlinkresult(handle): - + ref_array = np.array([4.631762, 1.0, 5.8973422, @@ -214,13 +216,13 @@ def test_getlinkresult(handle): 3.8141515]) test_array = smo.getlinkresult(handle, 3, 3) - + assert len(test_array) == 7 assert np.allclose(test_array, ref_array) def test_getsystemresult(handle): - + ref_array = np.array([70.0, 0.1, 0.0, @@ -237,7 +239,6 @@ def test_getsystemresult(handle): 0.0]) test_array = smo.getsystemresult(handle, 4, 4) - + assert len(test_array) == 14 assert np.allclose(test_array, ref_array) - \ No newline at end of file diff --git a/toolkit/setup.py b/swmm_python/toolkit/setup.py similarity index 71% rename from toolkit/setup.py rename to swmm_python/toolkit/setup.py index 9aa25863..5e436df1 100644 --- a/toolkit/setup.py +++ b/swmm_python/toolkit/setup.py @@ -2,13 +2,13 @@ # # setup.py - Setup script for swmm_toolkit python extension -# +# # Created: 7/2/2018 # Author: Michael E. Tryby # US EPA - ORD/NRMRL # # Requires: -# Platform C language compiler +# Platform C language compiler # SWIG # @@ -20,23 +20,25 @@ from distutils.command.build_ext import build_ext +microlib_name = 'swmm.toolkit' + setup( - name = 'swmm_toolkit', + name = microlib_name, version = '0.2.0-dev', ext_modules = [ Extension('swmm.toolkit._toolkit', sources = ['swmm/toolkit/toolkit.i'], swig_opts=['-py3'], - include_dirs = ['swmm/toolkit/'], - library_dirs = ['swmm/toolkit/'], + include_dirs = ['swmm/toolkit/'], + library_dirs = ['swmm/toolkit/'], libraries = ['swmm5'], extra_compile_args = ["/D WITH_GENX"], language = 'C' ) ], - - packages=['swmm.toolkit'], + namespace_packages=['swmm'], + packages=[microlib_name], py_modules = ['toolkit'], - package_data = {'swmm.toolkit':['*swmm5.dll', '*swmm5.so']}, + package_data = {microlib_name:['*swmm5.dll', '*swmm5.so']}, ) diff --git a/toolkit/swmm/toolkit/__init__.py b/swmm_python/toolkit/swmm/toolkit/__init__.py similarity index 100% rename from toolkit/swmm/toolkit/__init__.py rename to swmm_python/toolkit/swmm/toolkit/__init__.py diff --git a/toolkit/swmm/toolkit/toolkit.i b/swmm_python/toolkit/swmm/toolkit/toolkit.i similarity index 100% rename from toolkit/swmm/toolkit/toolkit.i rename to swmm_python/toolkit/swmm/toolkit/toolkit.i diff --git a/toolkit/tests/data/Example1.inp b/swmm_python/toolkit/tests/data/Example1.inp similarity index 100% rename from toolkit/tests/data/Example1.inp rename to swmm_python/toolkit/tests/data/Example1.inp diff --git a/toolkit/tests/test_toolkit.py b/swmm_python/toolkit/tests/test_toolkit.py similarity index 75% rename from toolkit/tests/test_toolkit.py rename to swmm_python/toolkit/tests/test_toolkit.py index 9c14dea3..58ca8b59 100644 --- a/toolkit/tests/test_toolkit.py +++ b/swmm_python/toolkit/tests/test_toolkit.py @@ -1,16 +1,20 @@ # # test_toolkit.py -# +# # Created: 8/8/2018 # Author: Michael E. Tryby # US EPA - ORD/NRMRL -# +# +import os import pytest from swmm.toolkit import toolkit as smtk -from data import INPUT_FILE_EXAMPLE_1, REPORT_FILE_TEST, OUTPUT_FILE_TEST +DATA_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') +INPUT_FILE_EXAMPLE_1 = os.path.join(DATA_PATH, 'Example1.inp') +REPORT_FILE_TEST = os.path.join(DATA_PATH, 'test.rpt') +OUTPUT_FILE_TEST = os.path.join(DATA_PATH, 'test.out') def test_allocfree(): @@ -19,44 +23,43 @@ def test_allocfree(): _handle = smtk.free_project(_handle) assert(_handle == None) - + def test_run(): _handle = smtk.alloc_project() smtk.run(_handle, INPUT_FILE_EXAMPLE_1, REPORT_FILE_TEST, OUTPUT_FILE_TEST) smtk.free_project(_handle) - - + + def test_openclose(): _handle = smtk.alloc_project() smtk.open(_handle, INPUT_FILE_EXAMPLE_1, REPORT_FILE_TEST, OUTPUT_FILE_TEST) smtk.close(_handle) smtk.free_project(_handle) - + @pytest.fixture() -def handle(request): +def handle(request): _handle = smtk.alloc_project() smtk.open(_handle, INPUT_FILE_EXAMPLE_1, REPORT_FILE_TEST, OUTPUT_FILE_TEST) - + def close(): smtk.close(_handle) smtk.free_project(_handle) - - request.addfinalizer(close) - return _handle + + request.addfinalizer(close) + return _handle def test_step(handle): - + smtk.start(handle, 0) - + while True: time = smtk.step(handle) - + if time == 0.: break smtk.end(handle) - - smtk.report(handle) + smtk.report(handle) diff --git a/toolkit/tests/data/__init__.py b/toolkit/tests/data/__init__.py deleted file mode 100644 index c21b1115..00000000 --- a/toolkit/tests/data/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ - - - -import os - -DATA_PATH = os.path.abspath(os.path.dirname(__file__)) - -INPUT_FILE_EXAMPLE_1 = os.path.join(DATA_PATH, 'Example1.inp') -REPORT_FILE_TEST = os.path.join(DATA_PATH, 'test.rpt') -OUTPUT_FILE_TEST = os.path.join(DATA_PATH, 'test.out') diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..f601a565 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ + + +[tox] +envlist = py36 + +[testenv] +whitelist_externals = + swig +skipsdist = True +usedevelop = True +deps = + pytest + numpy + aenum +commands = + python -m pytest --color=yes swmm_python -s