diff --git a/.github/workflows/build_deploy_pages.yml b/.github/workflows/build_deploy_pages.yml
index 7c7014a8..0b2f7630 100644
--- a/.github/workflows/build_deploy_pages.yml
+++ b/.github/workflows/build_deploy_pages.yml
@@ -1,4 +1,4 @@
-name: docs
+name: Build and Deploy Documentation
on:
push:
@@ -39,8 +39,8 @@ jobs:
if: github.event_name == 'push'
permissions:
contents: read
- pages: write # to deploy to Pages
- id-token: write # to verify the deployment originates from an appropriate source
+ pages: write # to deploy to Pages
+ id-token: write # to verify the deployment originates from an appropriate source
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
diff --git a/.github/workflows/build_test_wheels.yml b/.github/workflows/build_test_wheels.yml
new file mode 100644
index 00000000..09fdaf3c
--- /dev/null
+++ b/.github/workflows/build_test_wheels.yml
@@ -0,0 +1,126 @@
+# Build wheels, sdist, and full wheel test matrix.
+# Runs on: push to main (including merges), publish_pypi.yml (tags), workflow_call, and monthly schedule.
+name: Build and Test Wheels
+
+on:
+ workflow_call: # For use by publish_pypi.yml
+ push:
+ branches: [main]
+ schedule:
+ - cron: '0 0 1 * *'
+
+jobs:
+ build_wheels:
+ name: Build wheels
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
+ fail-fast: false
+ steps:
+ - name: Set env variables to handle macOS-15
+ if: ${{ matrix.os == 'macos-15-intel'}}
+ run: |
+ echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV
+ echo "PLAT=macosx-15.0-universal2" >> $GITHUB_ENV
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Install libomp on macos
+ if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
+ run: |
+ brew reinstall libomp
+ - name: Ad-hoc codesign for Apple Silicon
+ if: ${{ matrix.os == 'macos-latest' }}
+ run: |
+ dylib_path="wntr/epanet/libepanet/darwin-arm"
+ if [ -d "$dylib_path" ]; then
+ for file in "$dylib_path"/*; do
+ [ -e "$file" ] && codesign -f -s - "$file"
+ done
+ fi
+ - name: Build wheels
+ uses: pypa/cibuildwheel@v3.1.4
+ env:
+ CIBW_ENVIRONMENT: BUILD_WNTR_EXTENSIONS='true'
+ CIBW_BUILD: cp310-* cp311-* cp312-* cp313-*
+ CIBW_SKIP: "*-win32 *-manylinux_i686 pp* *-musllinux*"
+ CIBW_REPAIR_WHEEL_COMMAND: '' # Skip repair step
+ - name: Set up Python for twine verification
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Verify wheels with twine
+ shell: bash
+ run: |
+ python -m pip install --upgrade pip twine
+ for wheel in ./wheelhouse/*.whl; do
+ twine check "$wheel"
+ done
+ - name: Fix linux wheel names # Temporary hack: rename linux -> manylinux2014 so PyPI accepts them without a proper repair step.
+ if: ${{ matrix.os == 'ubuntu-latest' }}
+ run: |
+ for file in ./wheelhouse/*.whl; do
+ [ -e "$file" ] || continue
+ new_file="${file/linux/manylinux2014}"
+ mv "$file" "$new_file"
+ done
+ - name: Upload wheels
+ uses: actions/upload-artifact@v4
+ with:
+ name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
+ path: ./wheelhouse/*.whl
+
+ build_sdist:
+ name: Build SDist
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Build SDist
+ run: pipx run build --sdist
+ - uses: actions/upload-artifact@v4
+ with:
+ name: sdist
+ path: dist/*.tar.gz
+
+ test_wheels:
+ name: Test wheels (${{ matrix.python-version }}, ${{ matrix.os }})
+ needs: build_wheels
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ python-version: ['3.10', '3.11', '3.12', '3.13']
+ os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
+ fail-fast: false
+ steps:
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Download wheels for this OS
+ uses: actions/download-artifact@v4
+ with:
+ pattern: cibw-wheels-${{ matrix.os }}-*
+ merge-multiple: true
+ - name: Checkout test assets
+ uses: actions/checkout@v4
+ with:
+ sparse-checkout: |
+ wntr/tests/
+ sparse-checkout-cone-mode: false
+ fetch-depth: 1
+ - name: Set mpl backend on windows
+ if: ${{ matrix.os == 'windows-latest' }}
+ run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV
+ shell: pwsh
+ - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
+ run: brew reinstall libomp
+ - name: Install wntr from wheel
+ run: |
+ python -m pip install --upgrade pip
+ pip install --pre --find-links=. "wntr[optional,test]"
+ python -c "import wntr; print(wntr.__version__)"
+ - name: Run tests against wheel
+ run: pytest wntr/tests/ --ignore=wntr/tests/test_demos.py --ignore=wntr/tests/test_examples.py
diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml
deleted file mode 100644
index caac8a6c..00000000
--- a/.github/workflows/build_tests.yml
+++ /dev/null
@@ -1,321 +0,0 @@
-# This workflow will install Python dependencies, run tests and lint with all currently supported python versions on all major plattforms
-# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
-
-name: GitHub CI
-
-on:
- push:
- branches: [ main, dev, release ]
- tags:
- - '*'
- pull_request:
- branches: [ main, dev, release ]
- schedule:
- - cron: '0 0 1 * *'
-
-jobs:
- build_wheels:
- name: Build wheels
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
- fail-fast: false
- steps:
- - name: Set env variables to handle macOS-15
- if: ${{ matrix.os == 'macos-15-intel'}}
- run: |
- echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV
- echo "PLAT=macosx-15.0-universal2" >> $GITHUB_ENV
- - name: Checkout repository
- uses: actions/checkout@v4
- - name: Install libomp on macos
- if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
- run: |
- brew reinstall libomp # EPANETMSX repo also has this line, maybe include? `brew link --force --overwrite libomp`
- - name: Ad-hoc codesign for Apple Silicon
- if: ${{ matrix.os == 'macos-latest' }}
- run: |
- dylib_path="wntr/epanet/libepanet/darwin-arm"
- if [ -d "$dylib_path" ]; then
- for file in "$dylib_path"/*; do
- [ -e "$file" ] && codesign -f -s - "$file"
- done
- fi
- - name: Build wheels
- uses: pypa/cibuildwheel@v3.1.4
- env:
- CIBW_ENVIRONMENT: BUILD_WNTR_EXTENSIONS='true'
- CIBW_BUILD: cp310-* cp311-* cp312-* cp313-*
- CIBW_SKIP: "*-win32 *-manylinux_i686 pp* *-musllinux*"
- CIBW_REPAIR_WHEEL_COMMAND: '' # Skip repair step
- - name: Set up Python for twine verification
- uses: actions/setup-python@v5
- with:
- python-version: '3.11'
- - name: Install twine and verify wheels
- shell: bash
- run: |
- python -m pip install --upgrade pip
- pip install twine
- for wheel in ./wheelhouse/*.whl; do
- echo "Verifying wheel: $wheel"
- twine check "$wheel"
- done
- # - name: Fix macos15 wheel names # For some reason, they come out as macos14 instead of macos15
- # if: ${{ matrix.os == 'macos-15-intel'}}
- # run: |
- # echo "=== Before renaming ==="
- # ls -la ./wheelhouse/
- # for file in ./wheelhouse/*.whl; do
- # echo "Original file: $file"
- # new_name=$(echo "$file" | sed 's/macosx_14_0/macosx_15_0/')
- # echo "New name: $new_name"
- # mv "$file" "$new_name"
- # done
- # echo "=== After renaming ==="
- # ls -la ./wheelhouse/
- - name: Fix linux wheel names # This is a bit dishonest, since the wheels are not properly repaired to be manylinux compatible. This is a (hopefully) temporary hack to get our wheels onto pypi.
- if: ${{ matrix.os == 'ubuntu-latest' }}
- run: |
- for file in ./wheelhouse/*.whl; do
- [ -e "$file" ] || continue
- new_file="${file/linux/manylinux2014}"
- mv "$file" "$new_file"
- echo "Renamed: $file -> $new_file"
- done
- - name: Upload wheels
- uses: actions/upload-artifact@v4
- with:
- name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
- path: ./wheelhouse/*.whl
-
- test_wheels:
- name: Test wheels
- needs: build_wheels
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- python-version: ['3.10', '3.11', '3.12', '3.13']
- os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
- fail-fast: false
- steps:
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
- - name: Download wheel
- uses: actions/download-artifact@v4
- with:
- # name: wntr_${{ matrix.python-version }}_${{ matrix.os }}.whl
- pattern: "cibw-wheels-*"
- merge-multiple: true
- - name: Install wntr
- run: |
- python -m pip install --upgrade pip
- pip install wheel "numpy>=2.2.6" scipy networkx pandas matplotlib setuptools
- pip install --no-index --pre --find-links=. wntr
- - name: Import wntr
- run: |
- python -c "import wntr"
- - name: Checkout requirements.txt
- uses: actions/checkout@v4
- with:
- sparse-checkout: |
- requirements.txt
- wntr/tests/
- examples/
- sparse-checkout-cone-mode: false
- fetch-depth: 1
- - name: Set mpl backend on windows
- if: ${{ matrix.os == 'windows-latest' }}
- run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV
- shell: pwsh
- - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
- run: |
- brew reinstall libomp
- - name: Test wntr
- run: |
- pip install --find-links=. --pre "wntr[optional,test]"
- pytest wntr/tests/ --ignore=wntr/tests/test_demos.py --ignore=wntr/tests/test_examples.py
-
- run_coverage:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- python-version: ['3.10', '3.11', '3.12', '3.13']
- os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
- fail-fast: false
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
- - name: Set mpl backend on windows
- if: ${{ matrix.os == 'windows-latest' }}
- run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV
- shell: pwsh
- - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
- run: |
- brew reinstall libomp
- - name: Install dependencies
- run: |
- python --version
- python -m pip install --upgrade pip
- python -m pip install -e .[optional,test]
- - name: Run Tests
- if: ${{ matrix.os != 'macos-latest' }}
- env:
- OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'"
- COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
- run: |
- coverage erase
- coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT -m pytest -m "not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr
- coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation
- - name: Run Tests (ARM-processor)
- if: ${{ matrix.os == 'macos-latest'}}
- # doctests are not flexible enough to skip EPANET=v2.0 errors on ARM processor, so do not run doctests on ARM system
- run: |
- coverage erase
- coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit="*/tests/*","*/sim/network_isolation/network_isolation.py","*/sim/aml/evaluator.py" -m pytest --doctest-modules --doctest-glob="*.rst" wntr
- env:
- COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
- - name: Save coverage
- uses: actions/upload-artifact@v4
- with:
- name: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
- path: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
- include-hidden-files: true
-
- combine_reports:
- needs: [ run_coverage ]
- runs-on: ubuntu-latest
- steps:
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: 3.11
- - uses: actions/checkout@v4
- - name: Install coverage
- run: |
- python -m pip install --upgrade pip
- python -m pip install -e .[optional,test]
- pip install coveralls
- - name: Download coverage artifacts from test matrix
- uses: actions/download-artifact@v4
- with:
- pattern: .coverage.*.ubuntu-latest # coverage from other OS cause problems
- - name: Setup coverage and combine reports
- run: coverage combine .coverage.*.ubuntu-latest
- - name: Create coverage report
- run: |
- echo "[paths]" > .coveragerc
- echo "source = " >> .coveragerc
- echo " wntr/" >> .coveragerc
- echo " wntr\\" >> .coveragerc
- echo " D:\\a\\WNTR\\WNTR\\wntr" >> .coveragerc
- echo " /home/runner/work/WNTR/WNTR/wntr" >> .coveragerc
- echo " /Users/runner/work/WNTR/WNTR/wntr" >> .coveragerc
- echo " ${{ github.workspace }}/wntr" >> .coveragerc
- coverage report
- coverage json --pretty-print
- coverage html --show-contexts
- - name: Save coverage JSON
- uses: actions/upload-artifact@v4
- with:
- name: coverage-json
- path: coverage.json
- - name: Save coverage html
- uses: actions/upload-artifact@v4
- with:
- name: coverage-html
- path: htmlcov
- - name: Push to coveralls
- run: coveralls --service=github --rcfile=.coveragerc
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- build_sdist:
- name: Build SDist artifact 📦
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
- with:
- python-version: '3.11'
- - name: Build SDist
- run: pipx run build --sdist
- - uses: actions/upload-artifact@v4
- with:
- name: sdist
- path: dist/*.tar.gz
-
- publish-to-testpypi:
- name: Publish Python 🐍 distribution 📦 to TestPyPI
- needs: [build_sdist, test_wheels]
- runs-on: ubuntu-latest
- environment:
- name: testpypi
- url: https://test.pypi.org/project/wntr
- permissions:
- id-token: write
- if: github.event_name == 'workflow_dispatch'
- steps:
- - name: Download wheel artifacts
- uses: actions/download-artifact@v4
- with:
- pattern: cibw-*
- path: dist
- merge-multiple: true
- - name: Download SDist artifact
- uses: actions/download-artifact@v4
- with:
- name: sdist
- path: dist
- - name: Debug wheel files before upload
- run: |
- echo "=== Wheel files to upload ==="
- ls -la dist/
- echo "=== Wheel file details ==="
- for wheel in dist/*.whl; do
- echo "File: $wheel"
- file "$wheel"
- unzip -l "$wheel" | head -10
- echo "---"
- done
- - name: Publish to TestPyPI
- uses: pypa/gh-action-pypi-publish@release/v1
- with:
- repository-url: https://test.pypi.org/legacy/
- user: __token__
- password: ${{ secrets.TEST_PYPI_API_TOKEN }}
- verbose: true
-
- publish-to-pypi:
- name: Publish Python 🐍 distribution 📦 to PyPI
- needs: [build_sdist, test_wheels]
- runs-on: ubuntu-latest
- environment:
- name: release
- permissions:
- id-token: write
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- steps:
- - name: Download wheel artifacts
- uses: actions/download-artifact@v4
- with:
- pattern: cibw-*
- path: dist
- merge-multiple: true
- - name: Download SDist artifact
- uses: actions/download-artifact@v4
- with:
- name: sdist
- path: dist
-
- - uses: pypa/gh-action-pypi-publish@release/v1
- with:
- user: __token__
- password: ${{ secrets.PYPI_WNTR_API_TOKEN }}
-
diff --git a/.github/workflows/publish_conda.yml b/.github/workflows/publish_conda.yml
new file mode 100644
index 00000000..49dea830
--- /dev/null
+++ b/.github/workflows/publish_conda.yml
@@ -0,0 +1,54 @@
+# Manually triggered: open a conda-forge feedstock PR for a published PyPI release.
+# Run this after confirming the version is live on https://pypi.org/project/wntr/.
+
+name: Publish to conda-forge
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version to release (e.g. 1.4.1) — must already be live on PyPI'
+ required: true
+ type: string
+
+jobs:
+ open-conda-forge-pr:
+ name: Open conda-forge feedstock PR
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+
+ - name: Install Grayskull
+ run: pip install grayskull
+
+ - name: Generate recipe with Grayskull
+ run: grayskull pypi wntr==${{ inputs.version }}
+
+ - name: Clone feedstock fork
+ run: |
+ git clone https://x-access-token:${{ secrets.CONDA_FORGE_TOKEN }}@github.com/${{ vars.CONDA_FORGE_FORK_OWNER }}/wntr-feedstock.git
+ cd wntr-feedstock
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git config user.name "github-actions[bot]"
+ git checkout -b release-${{ inputs.version }}
+
+ - name: Patch feedstock recipe
+ run: python wntr-feedstock/recipe/patch_meta.py wntr/meta.yaml wntr-feedstock/recipe/meta.yaml
+
+ - name: Push branch and open PR
+ env:
+ GH_TOKEN: ${{ secrets.CONDA_FORGE_TOKEN }}
+ run: |
+ cd wntr-feedstock
+ git add recipe/meta.yaml
+ git commit -m "Update WNTR to ${{ inputs.version }}"
+ git push origin release-${{ inputs.version }}
+
+ gh pr create \
+ --repo conda-forge/wntr-feedstock \
+ --head ${{ vars.CONDA_FORGE_FORK_OWNER }}:release-${{ inputs.version }} \
+ --title "Update WNTR to ${{ inputs.version }}" \
+ --body ""
diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml
new file mode 100644
index 00000000..c8108b9c
--- /dev/null
+++ b/.github/workflows/publish_pypi.yml
@@ -0,0 +1,37 @@
+# Triggered on version tag push: build wheels, full wheel test matrix, publish to PyPI.
+# Tests are expected to have already passed on main before tagging.
+name: Publish to PyPI
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ wheels:
+ name: Build and Test Wheels
+ uses: ./.github/workflows/build_test_wheels.yml
+
+ publish-to-pypi:
+ name: Publish to PyPI
+ needs: [wheels]
+ runs-on: ubuntu-latest
+ environment:
+ name: release
+ url: https://pypi.org/project/wntr/
+ permissions:
+ id-token: write
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ pattern: cibw-wheels-*
+ path: dist
+ merge-multiple: true
+ - uses: actions/download-artifact@v4
+ with:
+ name: sdist
+ path: dist
+ - uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_WNTR_API_TOKEN }}
diff --git a/.github/workflows/quick_check.yml b/.github/workflows/quick_check.yml
deleted file mode 100644
index 7a9ae0ce..00000000
--- a/.github/workflows/quick_check.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-# This workflow will install Python dependencies, run tests and lint with a single version of Python
-# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
-
-name: quick-check
-
-on:
- push:
- branches:
- - '**'
- pull_request:
- branches:
- - '**'
-
-jobs:
- test:
- strategy:
- matrix:
- python-version: ['3.11', '3.13']
- fail-fast: false
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install packages
- run: |
- python -m pip install --upgrade pip
- pip install -e .[optional,test]
- - name: Run tests and coverage (unittests plus doctests)
- env:
- OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'"
- run: |
- coverage run --source=wntr --omit=$OMIT -m pytest -m "not time_consuming and not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr
- coverage run --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation
- coverage report --fail-under=70
- # coverage run --source=wntr --omit="*/tests/*" --append -m pytest --doctest-glob="*.rst" documentation
-
diff --git a/.github/workflows/extensions.yml b/.github/workflows/test_extensions.yml
similarity index 92%
rename from .github/workflows/extensions.yml
rename to .github/workflows/test_extensions.yml
index b7fd98b4..ccc13187 100644
--- a/.github/workflows/extensions.yml
+++ b/.github/workflows/test_extensions.yml
@@ -1,7 +1,7 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
-name: extensions
+name: Test Extensions
on:
push:
@@ -12,7 +12,8 @@ on:
- '**'
jobs:
- test:
+ test:
+ name: Test Extensions (${{ matrix.python-version }})
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
diff --git a/.github/workflows/test_repository.yml b/.github/workflows/test_repository.yml
new file mode 100644
index 00000000..8bcc8f7b
--- /dev/null
+++ b/.github/workflows/test_repository.yml
@@ -0,0 +1,111 @@
+# Tests editable install (`pip install -e .`), full OS/Python matrix, coverage, Coveralls.
+
+name: Test Repository
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+ schedule:
+ - cron: '0 0 1 * *'
+
+jobs:
+ run_coverage:
+ name: Run Coverage (${{ matrix.python-version }}, ${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ python-version: ['3.10', '3.11', '3.12', '3.13']
+ os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
+ fail-fast: false
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Set mpl backend on windows
+ if: ${{ matrix.os == 'windows-latest' }}
+ run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV
+ shell: pwsh
+ - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}}
+ run: |
+ brew reinstall libomp
+ - name: Install dependencies
+ run: |
+ python --version
+ python -m pip install --upgrade pip
+ python -m pip install -e .[optional,test]
+ - name: Run Tests
+ if: ${{ matrix.os != 'macos-latest' }}
+ env:
+ OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'"
+ COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
+ run: |
+ coverage erase
+ coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT -m pytest -m "not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr
+ coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation
+ - name: Run Tests (ARM-processor)
+ if: ${{ matrix.os == 'macos-latest'}}
+ # doctests are not flexible enough to skip EPANET=v2.0 errors on ARM processor, so do not run doctests on ARM system
+ run: |
+ coverage erase
+ coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit="*/tests/*","*/sim/network_isolation/network_isolation.py","*/sim/aml/evaluator.py" -m pytest --doctest-modules --doctest-glob="*.rst" wntr
+ env:
+ COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
+ - name: Save coverage
+ uses: actions/upload-artifact@v4
+ with:
+ name: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
+ path: .coverage.${{ matrix.python-version }}.${{ matrix.os }}
+ include-hidden-files: true
+
+ combine_reports:
+ name: Combine Coverage and Upload to Coveralls
+ needs: [ run_coverage ]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.11
+ - uses: actions/checkout@v4
+ - name: Install coverage
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install -e .[optional,test]
+ pip install coveralls
+ - name: Download coverage artifacts from test matrix
+ uses: actions/download-artifact@v4
+ with:
+ pattern: .coverage.*.ubuntu-latest # coverage from other OS cause problems
+ - name: Setup coverage and combine reports
+ run: coverage combine .coverage.*.ubuntu-latest
+ - name: Create coverage report
+ run: |
+ echo "[paths]" > .coveragerc
+ echo "source = " >> .coveragerc
+ echo " wntr/" >> .coveragerc
+ echo " wntr\\" >> .coveragerc
+ echo " D:\\a\\WNTR\\WNTR\\wntr" >> .coveragerc
+ echo " /home/runner/work/WNTR/WNTR/wntr" >> .coveragerc
+ echo " /Users/runner/work/WNTR/WNTR/wntr" >> .coveragerc
+ echo " ${{ github.workspace }}/wntr" >> .coveragerc
+ coverage report
+ coverage json --pretty-print
+ coverage html --show-contexts
+ - name: Save coverage JSON
+ uses: actions/upload-artifact@v4
+ with:
+ name: coverage-json
+ path: coverage.json
+ - name: Save coverage html
+ uses: actions/upload-artifact@v4
+ with:
+ name: coverage-html
+ path: htmlcov
+ - name: Push to coveralls
+ run: coveralls --service=github --rcfile=.coveragerc
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.md b/README.md
index 1371a925..86d4705a 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-[](https://github.com/USEPA/WNTR/actions/workflows/build_tests.yml)
+[](https://github.com/USEPA/WNTR/actions/workflows/test_repository.yml)
[](https://coveralls.io/github/USEPA/WNTR?branch=main)
[](https://github.com/usepa/wntr/actions/workflows/build_deploy_pages.yml)
[](https://github.com/USEPA/WNTR/graphs/contributors)
diff --git a/documentation/developers.rst b/documentation/developers.rst
index dad8da7f..4637d08a 100644
--- a/documentation/developers.rst
+++ b/documentation/developers.rst
@@ -136,7 +136,7 @@ Extensions adhere to the following file structure:
2) a point of contact (developer name and GitHub username), and
3) supporting documentation and examples (using doctest).
A link to the documentation should also be added to ``documentation\extensions.rst`` and ``documentation\userguide.rst``.
-* **Testing**: Tests are run using the `extensions workflow `_.
+* **Testing**: Tests are run using the `test_extensions workflow `_.
Tests reside in a file named ``wntr\tests\extensions\test_.py``.
Tests should be marked ``@pytest.mark.extensions``.
* **Requirements**: If the extension requires packages beyond WNTR's core dependencies, add a corresponding entry to
diff --git a/documentation/extensions.rst b/documentation/extensions.rst
index 7101f1c6..5aa8b7de 100644
--- a/documentation/extensions.rst
+++ b/documentation/extensions.rst
@@ -8,8 +8,8 @@ Extensions
==========
|extensions|
-.. |extensions| image:: https://github.com/USEPA/WNTR/actions/workflows/extensions.yml/badge.svg
- :target: https://github.com/USEPA/WNTR/actions/workflows/extensions.yml
+.. |extensions| image:: https://github.com/USEPA/WNTR/actions/workflows/test_extensions.yml/badge.svg
+ :target: https://github.com/USEPA/WNTR/actions/workflows/test_extensions.yml
WNTR extensions are intended to house beta and self-contained functionality that adds to WNTR,
but is currently not part of core WNTR development. The extensions should be designed for a wide audience.
diff --git a/documentation/installation.rst b/documentation/installation.rst
index eea8aef8..159f7dc4 100644
--- a/documentation/installation.rst
+++ b/documentation/installation.rst
@@ -236,7 +236,7 @@ the shared object files can be downloaded from WNTR GitHub Actions using the fol
python -m pip install -e . --no-build
pip install -r requirements.txt
-* Select the latest GitHub Actions build_tests that uses the main branch from https://github.com/USEPA/WNTR/actions/workflows/build_tests.yml
+* Select the latest successful run of the wheel workflow on the main branch from https://github.com/USEPA/WNTR/actions/workflows/build_test_wheels.yml
* Scroll down to "Artifacts"
* Download the wheel that matches the desired operating system and Python version (for example, wntr_3.9_windows-latest.whl)
* Unzip the wheel and locate the following files (which are named according to the operating system and Python version)