Skip to content

Commit c229e47

Browse files
authored
Build wheels on Appveyor for py36 py37 (#30)
* Omitting tests from coverage * Adding py37 to tox.ini * Running tests on py37 * Rolling back changes, configuring cache * Adding .tox to appveyor cache * Experimenting with cibuildwheel * Experimenting with cibuildwheel * More xp * Adding python -version * before-build now returns to project root dir before exiting * Skipping py27 and win32 builds * Trying to get cibuildwheel to run under py35 * Increase logging level * Build verbosity 3 * Adding six to setup_requires * Adding six to install * installing six with CIBW_BEFORE_BUILD * Targeting py36 and py37 * Skipping 32-bit builds * Building microlibs * running tests on wheels * running tests * Omitting top level namespace directory * Tests require numpy * Adding output.py module file to package data * Trying to get module file to add * So tired of this not working * reworking setup.py for native namespace package * Trying custom build_py command * SWIG wrapper generation moved to before-build.bat * Working on setup * Updating comments * Commenting on cibuildwheel for now * bumping version, configuring cibuildwheel to run after tests pass * configuring cibuildwheel run after test * swmm_python doesn't declare a namespace package * Tweaking setup so tests load in tox * Getting tox test and cibuildwheel to both work * Another try * Switching to Py36-x64 * pytest==4.2.0 * Rolling back appveyor.yml * Adding py35 to cibuildwheel * cibuildwheel configured for py36 and py37
1 parent 3a168bf commit c229e47

File tree

7 files changed

+132
-88
lines changed

7 files changed

+132
-88
lines changed

appveyor.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
environment:
44
passphrase:
55
secure: En1qcj1/l2B3Nov+vOHlfRrFZk00bg1HPRouD64Gzfw=
6+
CIBW_SKIP: cp27-* cp34-* cp35-* *-win32
7+
CIBW_BEFORE_BUILD: pip install six
8+
CIBW_TEST_COMMAND: pytest {project}\\tests
9+
CIBW_TEST_REQUIRES: pytest numpy
10+
611
matrix:
712
- PYTHON: "C:\\Python36-x64"
813

@@ -17,5 +22,19 @@ build: off
1722

1823

1924
test_script:
20-
- before_build.bat %APPVEYOR_BUILD_FOLDER%
25+
- before_build.bat
2126
- "%PYTHON%\\python.exe -m tox -v"
27+
28+
after_test:
29+
- "%PYTHON%\\python.exe -m pip install cibuildwheel==0.10.1"
30+
- "%PYTHON%\\python.exe -m cibuildwheel --output-dir wheelhouse .\\swmm_python\\output"
31+
- "%PYTHON%\\python.exe -m cibuildwheel --output-dir wheelhouse .\\swmm_python\\toolkit"
32+
33+
artifacts:
34+
- path: "wheelhouse\\*.whl"
35+
name: Wheels
36+
37+
cache:
38+
- C:\ProgramData\chocolatey\bin -> appveyor.yml
39+
- C:\ProgramData\chocolatey\lib -> appveyor.yml
40+
- C:\projects\swmm-python\.tox -> tox.ini

before_build.bat

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,55 @@
66
:: Author: Michael E. Tryby
77
:: US EPA - ORD/NRMRL
88
::
9+
:: Requires:
10+
:: CMake
11+
:: Visual Studio 2015
12+
:: SWIG
13+
::
14+
:: Note:
15+
:: This script must be located at the root of the project folder
16+
: in order to work correctly.
17+
::
918

10-
set PROJECT_PATH=%~1
1119

12-
set TOOLKIT_PATH=\swmm_python\toolkit\swmm\toolkit
13-
set OUTPUT_PATH=\swmm_python\output\swmm\output
20+
:: Determine project path and strip trailing \ from path
21+
set "PROJECT_PATH=%~dp0"
22+
IF %PROJECT_PATH:~-1%==\ set "PROJECT_PATH=%PROJECT_PATH:~0,-1%"
1423

24+
set "TOOLKIT_PATH=swmm_python\toolkit\swmm\toolkit"
25+
set "OUTPUT_PATH=swmm_python\output\swmm\output"
1526

27+
28+
:: Clone the project
1629
mkdir buildlib
1730
cd buildlib
1831
git clone --branch=feature-wrapper https://github.com/michaeltryby/Stormwater-Management-Model.git swmm
19-
cd swmm
32+
cd swmm
2033

2134

35+
:: Build the project
2236
mkdir buildprod
2337
cd buildprod
2438
cmake -G"Visual Studio 14 2015 Win64" -DBUILD_TESTS=0 ..
2539
cmake --build . --config Release
2640

2741

42+
:: Copy files required for python package build
2843
copy /Y .\bin\Release\swmm5.dll %PROJECT_PATH%\%TOOLKIT_PATH%
2944
copy /Y .\lib\Release\swmm5.lib %PROJECT_PATH%\%TOOLKIT_PATH%
3045
copy /Y ..\include\*.h %PROJECT_PATH%\%TOOLKIT_PATH%
3146

3247
copy /Y .\bin\Release\swmm-output.dll %PROJECT_PATH%\%OUTPUT_PATH%
3348
copy /Y .\lib\Release\swmm-output.lib %PROJECT_PATH%\%OUTPUT_PATH%
3449
copy /Y ..\tools\swmm-output\include\*.h %PROJECT_PATH%\%OUTPUT_PATH%
50+
51+
52+
:: Generate swig wrappers
53+
cd %PROJECT_PATH%\%TOOLKIT_PATH%
54+
swig -python -py3 toolkit.i
55+
cd %PROJECT_PATH%\%OUTPUT_PATH%
56+
swig -python -py3 output.i
57+
58+
59+
:: Return to project root
60+
cd %PROJECT_PATH%

setup.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323

2424
def install_microlibs(sources, develop=False):
2525
""" Use pip to install all microlibraries. """
26-
print("installing all microlibs in {} mode".format(
27-
"development" if develop else "normal"))
26+
print("installing all microlibs in {} mode".format("development" if develop else "normal"))
2827
wd = pathlib.Path.cwd()
2928
for k, v in iteritems(sources):
3029
try:
@@ -56,18 +55,26 @@ def run(self):
5655

5756
setup(
5857
name=PACKAGE_NAME,
59-
version="0.2.0a",
58+
version="0.3.0.dev0",
59+
60+
cmdclass={
61+
'install': InstallCmd,
62+
'develop': DevelopCmd
63+
},
64+
6065
author="Michael Tryby",
6166
author_email="Michael [email protected]",
6267
description="swmm_python - SWIG generated python wrappers for swmm libraries",
6368
license="CC0",
6469
classifiers=[
6570
'Private :: Do Not Upload to pypi server',
6671
],
67-
cmdclass={
68-
'install': InstallCmd,
69-
'develop': DevelopCmd
70-
},
71-
setup_requires=["pytest-runner"],
72-
tests_require=["pytest"]
72+
73+
setup_requires=[
74+
'pytest-runner'
75+
],
76+
tests_require=[
77+
'pytest==4.2.0',
78+
'numpy'
79+
]
7380
)

swmm_python/output/setup.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,34 @@
99
#
1010
# Requires:
1111
# Platform C language compiler
12-
# SWIG
1312
#
1413

15-
try:
16-
from setuptools import setup, Extension
17-
from setuptools.command.build_ext import build_ext
18-
except ImportError:
19-
from distutils.core import setup, Extension
20-
from distutils.command.build_ext import build_ext
2114

15+
from setuptools import setup, Extension
16+
from setuptools.command.build_ext import build_ext
2217

23-
microlib_name = 'swmm.output'
2418

2519
setup(
26-
name = microlib_name,
27-
version = "0.3.0-dev",
20+
name = 'swmm.output',
21+
version = "0.4.0.dev0",
2822

2923
ext_modules = [
3024
Extension("swmm.output._output",
25+
sources = ['swmm/output/output_wrap.c'],
3126
include_dirs = ['swmm/output/'],
3227
libraries = ['swmm-output'],
3328
library_dirs = ['swmm/output/'],
34-
sources = ['swmm/output/output.i'],
35-
swig_opts=['-py3'],
3629
language='C'
3730
)
3831
],
39-
namespace_packages=['swmm'],
40-
packages = [microlib_name],
32+
# tox can't find swmm module at test time unless namespace is declared
33+
namespace_packages = ['swmm'],
34+
35+
packages = ['swmm.output'],
4136
py_modules = ['output'],
42-
package_data = {microlib_name:['*swmm-output.dll', '*swmm-output.so']},
37+
package_data = {'swmm.output':['./*swmm-output.dll', './*swmm-output.so']},
38+
39+
zip_safe=False,
4340

4441
install_requires = [
4542
'aenum'

swmm_python/output/swmm/output/__init__.py

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#
44
# __init__.py - SWMM output package
5-
#
5+
#
66
# Date Created: August 9, 2018
77
#
88
# Author: Michael E. Tryby
@@ -27,28 +27,28 @@
2727
__status = "Development"
2828

2929

30-
from enum import Enum, auto
30+
from enum import Enum
3131
from aenum import extend_enum
3232
from itertools import islice
3333

3434
from swmm.output import output as oapi
3535

3636

3737
class Units(Enum):
38-
RAIN_INT = auto()
39-
SNOW_DEPTH = auto()
40-
EVAP_RATE = auto()
41-
INFIL_RATE = auto()
42-
FLOW_RATE = auto()
43-
ELEV = auto()
44-
PERCENT = auto()
45-
CONCEN = auto()
46-
HEAD = auto()
47-
VOLUME = auto()
48-
VELOCITY = auto()
49-
TEMP = auto()
50-
UNITLESS = auto()
51-
NONE = auto()
38+
RAIN_INT = 1
39+
SNOW_DEPTH = 2
40+
EVAP_RATE = 3
41+
INFIL_RATE = 4
42+
FLOW_RATE = 5
43+
ELEV = 6
44+
PERCENT = 7
45+
CONCEN = 8
46+
HEAD = 9
47+
VOLUME = 10
48+
VELOCITY = 11
49+
TEMP = 12
50+
UNITLESS = 13
51+
NONE = 14
5252

5353

5454
class OutputMetadata:
@@ -91,11 +91,11 @@ class OutputMetadata:
9191
Units.VELOCITY: "m/sec",
9292
Units.TEMP: "deg C",
9393
Units.UNITLESS: "unitless",
94-
Units.NONE: "",
94+
Units.NONE: "",
9595

9696
oapi.FlowUnits.CMS: "cu m/sec",
9797
oapi.FlowUnits.LPS: "L/sec",
98-
oapi.FlowUnits.MLD: "M L/day",
98+
oapi.FlowUnits.MLD: "M L/day",
9999

100100
oapi.ConcUnits.MG: "mg/L",
101101
oapi.ConcUnits.UG: "ug/L",
@@ -106,21 +106,21 @@ class OutputMetadata:
106106

107107
def _build_pollut_metadata(self, output_handle):
108108
'''
109-
Builds metadata for pollutant attributes at runtime.
110-
'''
109+
Builds metadata for pollutant attributes at runtime.
110+
'''
111111
# Get number of pollutants
112112
n = oapi.getprojectsize(output_handle)[oapi.ElementType.POLLUT]
113113

114114
if n > 0:
115-
115+
116116
pollut_name = []
117117
pollut_units = []
118-
118+
119119
# Get pollutant names
120120
for i in range(0, n):
121-
pollut_name.append(oapi.getelementname(output_handle,
121+
pollut_name.append(oapi.getelementname(output_handle,
122122
oapi.ElementType.POLLUT, i))
123-
# Get pollutant units
123+
# Get pollutant units
124124
for u in oapi.getunits(output_handle)[2:]:
125125
pollut_units.append(oapi.ConcUnits(u))
126126

@@ -130,32 +130,32 @@ def _build_pollut_metadata(self, output_handle):
130130
extend_enum(oapi.SubcatchAttribute, symbolic_name, 8 + i)
131131
extend_enum(oapi.NodeAttribute, symbolic_name, 6 + i)
132132
extend_enum(oapi.LinkAttribute, symbolic_name, 5 + i)
133-
133+
134134
# Update metadata dictionary with pollutant metadata
135135
for i, attr in enumerate(islice(oapi.SubcatchAttribute, 8, None)):
136-
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
137-
136+
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
137+
138138
for i, attr in enumerate(islice(oapi.NodeAttribute, 6, None)):
139-
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
140-
139+
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
140+
141141
for i, attr in enumerate(islice(oapi.LinkAttribute, 5, None)):
142-
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
143-
142+
self._metadata[attr] = (pollut_name[i], self._unit_labels[pollut_units[i]])
143+
144144

145145
def __init__(self, output_handle):
146146
# Get units from binary output file
147147
self.units = oapi.getunits(output_handle)
148-
148+
149149
# Determine prevailing unit system
150150
self._unit_system = oapi.UnitSystem(self.units[0])
151151
if self._unit_system == oapi.UnitSystem.US:
152152
self._unit_labels = type(self)._unit_labels_us_
153153
else:
154154
self._unit_labels = type(self)._unit_labels_si_
155-
156-
# Set user flow units
155+
156+
# Set user flow units
157157
self._flow = oapi.FlowUnits(self.units[1])
158-
158+
159159
self._metadata = {
160160
oapi.SubcatchAttribute.RAINFALL: ("Rainfall", self._unit_labels[Units.RAIN_INT]),
161161
oapi.SubcatchAttribute.SNOW_DEPTH: ("Snow Depth", self._unit_labels[Units.SNOW_DEPTH]),
@@ -197,7 +197,7 @@ def __init__(self, output_handle):
197197
oapi.SystemAttribute.VOLUME_STORED: ("Volume Stored", self._unit_labels[Units.VOLUME]),
198198
oapi.SystemAttribute.EVAP_RATE: ("Evaporation Rate", self._unit_labels[Units.EVAP_RATE])
199199
}
200-
200+
201201
self._build_pollut_metadata(output_handle)
202202

203203

@@ -206,20 +206,20 @@ def get_attribute_metadata(self, attribute):
206206
Takes an attribute enum and returns the name and units in a tuple.
207207
'''
208208
return self._metadata[attribute]
209-
210-
209+
210+
211211
# Units of Measurement
212212
#
213-
# Units US Customary SI Metric
213+
# Units US Customary SI Metric
214214
# AREA_SUBCATCH acres ac hectares ha
215215
# AREA_STOR square feet sq ft square meters sq m
216216
# AREA_POND square feet sq ft square meters sq m
217217
# CAP_SUC inches in millimeters mm
218-
# CONC milligrams/liter mg/L milligrams/liter mg/L
218+
# CONC milligrams/liter mg/L milligrams/liter mg/L
219219
# micrograms/liter ug/L micrograms/liter ug/L
220220
# counts/liter Count/L counts/liter Count/L
221221
# INFIL_DECAY 1/hours 1/hrs 1/hours 1/hrs
222-
# POLLUT_DECAY 1/days 1/days 1/days 1/days
222+
# POLLUT_DECAY 1/days 1/days 1/days 1/days
223223
# DEPRES_STOR inches in millimeters mm
224224
# DEPTH feet ft meters m
225225
# DIAM feet ft meters m
@@ -244,5 +244,3 @@ def get_attribute_metadata(self, attribute):
244244
# STREET_CLEAN_INT days days days days
245245
# VOLUME cubic feet cu ft cubic meters cu m
246246
# WIDTH feet ft meters m
247-
248-

0 commit comments

Comments
 (0)