Skip to content

Add 9.4.5.0 to tests #1793

Add 9.4.5.0 to tests

Add 9.4.5.0 to tests #1793

Workflow file for this run

# There are three things in this file that need regular maintenance:
#
# 1) Updating GraphBLAS version
# - We should probably make this a variable to make it easier to change
# 2) Updating dependency versions in "Update env"
# - This typically means adding new major versions of packages
# - `scripts/check_versions.sh` may be helpful to get version info
# 3) Updating Python versions (search for "Python version" or "pyver")
name: Tests
on:
# Run this workflow every time a PR is opened or a new commit is pushed to the PR
pull_request:
# Run this workflow every time a PR is merged to main
push:
branches:
- main
# concurrency:
# group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
# cancel-in-progress: true
jobs:
rngs:
# To achieve consistent coverage, we need a little bit of correlated collaboration.
# Specifically, we need to make sure we run with and without `--mapnumpy` on slow tests.
# We also use correlated RNG to run both backends on slow tests.
#
# {A,B,C,D},yes = --mapnumpy
# {A,B,C,D},no = --no-mapnumpy
# {D,E,F,G},yes = --backend=suitesparse
# {D,E,F,G},no = --backend=suitesparse-vanilla
#
# linux windows osx
# +-----------------------+
# A E normal | yes no |
# A E bizarro | no yes |
# B F normal | no yes |
# B F bizarro | yes no |
# C G normal | no yes |
# C G bizarro | yes no |
# D H normal | yes no |
# D H bizarro | no yes |
# +-----------------------+
runs-on: ubuntu-latest
outputs:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs
mapnumpy: ${{ steps.mapnumpy.outputs.selected }}
backend: ${{ steps.backend.outputs.selected }}
steps:
- name: RNG for mapnumpy
uses: ddradar/choose-random-action@v3.0.0
id: mapnumpy
with:
contents: |
A
B
C
D
weights: |
1
1
1
1
- name: RNG for backend
uses: ddradar/choose-random-action@v3.0.0
id: backend
with:
contents: |
E
F
G
H
weights: |
1
1
1
1
build_and_test:
needs: rngs
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash -l {0}
strategy:
# To "stress test" in CI, set `fail-fast` to `false` and use `repeat` in matrix below
fail-fast: false
# The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype].
# This should ensure we'll have full code coverage (i.e., no chance of getting unlucky),
# since we need to run all slow tests on Windows and non-Windoes OSes.
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
slowtask: ["pytest_normal", "pytest_bizarro", "notebooks"]
# repeat: [1, 2, 3] # For stress testing
env:
# Wheels on OS X come with an OpenMP that conflicts with OpenMP from conda-forge.
# Setting this is a workaround.
KMP_DUPLICATE_LIB_OK: ${{ contains(matrix.os, 'macos') && 'TRUE' || 'FALSE' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: RNG for Python version
uses: ddradar/choose-random-action@v3.0.0
id: pyver
with:
# We should support major Python versions for at least 36 months as per SPEC 0
# We may be able to support pypy if anybody asks for it
# 3.9.16 0_73_pypy
contents: |
3.10
3.11
3.12
3.13
weights: |
1
1
1
1
- name: RNG for source of python-suitesparse-graphblas
uses: ddradar/choose-random-action@v3.0.0
id: sourcetype
with:
# Weights must be natural numbers, so set weights to very large to skip one
# (such as if 'upstream' is known to not work).
contents: |
conda-forge
wheel
source
upstream
weights: |
1
1
1
1
- name: Setup conda
uses: conda-incubator/setup-miniconda@v3
id: setup_conda
with:
auto-update-conda: true
python-version: ${{ steps.pyver.outputs.selected }}
channels: conda-forge${{ contains(steps.pyver.outputs.selected, 'pypy') && ',defaults' || '' }}
conda-remove-defaults: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'false' || 'true' }}
channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }}
activate-environment: graphblas
auto-activate-base: false
- name: Update env
run: |
# Install dependencies based on the needs of the job.
# Don't panic! This may look scary at a glance, but each line makes sense.
#
# First let's randomly get versions of dependencies to install.
# Consider removing old versions when they become problematic or very old (>=2 years).
# Randomly choosing versions of dependencies based on Python version works surprisingly well...
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.10') }} == true ]]; then
nxver=$(python -c 'import random ; print(random.choice(["=2.8", "=3.0", "=3.1", "=3.2", "=3.3", "=3.4", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.24", "=1.25", "=1.26", "=2.0", "=2.1", "=2.2", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=1.11", "=1.12", "=1.13", "=1.14", "=1.15", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", "=2.1", "=2.2", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", "=2.2", "=2.3", "=2.4", "=2.5", "=2.6", "=2.7", ""]))')
fmmver=$(python -c 'import random ; print(random.choice(["=1.4", "=1.5", "=1.6", "=1.7", ""]))')
yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))')
sparsever=$(python -c 'import random ; print(random.choice(["=0.14", "=0.15", ""]))')
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]]; then
nxver=$(python -c 'import random ; print(random.choice(["=2.8", "=3.0", "=3.1", "=3.2", "=3.3", "=3.4", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.24", "=1.25", "=1.26", "=2.0", "=2.1", "=2.2", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=1.11", "=1.12", "=1.13", "=1.14", "=1.15", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", "=2.1", "=2.2", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", "=2.2", "=2.3", "=2.4", "=2.5", "=2.6", "=2.7", ""]))')
fmmver=$(python -c 'import random ; print(random.choice(["=1.4", "=1.5", "=1.6", "=1.7", ""]))')
yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))')
sparsever=$(python -c 'import random ; print(random.choice(["=0.14", "=0.15", ""]))')
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.12') }} == true ]]; then
nxver=$(python -c 'import random ; print(random.choice(["=3.2", "=3.3", "=3.4", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.26", "=2.0", "=2.1", "=2.2", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.11", "=1.12", "=1.13", "=1.14", "=1.15", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=2.1", "=2.2", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=2.4", "=2.5", "=2.6", "=2.7", ""]))')
fmmver=$(python -c 'import random ; print(random.choice(["=1.7", ""]))')
yamlver=$(python -c 'import random ; print(random.choice(["=6.0", ""]))')
sparsever=$(python -c 'import random ; print(random.choice(["=0.14", "=0.15", ""]))')
else # Python 3.13
nxver=$(python -c 'import random ; print(random.choice(["=3.4", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=2.1", "=2.2", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.14", "=1.15", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=2.2", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=2.7", ""]))')
fmmver=NA # Not yet supported
yamlver=$(python -c 'import random ; print(random.choice(["=6.0", ""]))')
sparsever=NA # Not yet supported
fi
# But there may be edge cases of incompatibility we need to handle (more handled below)
if [[ ${{ steps.sourcetype.outputs.selected }} == "source" ]]; then
# TODO: there are currently issues with some numpy versions when
# installing python-suitesparse-grphblas from source.
npver=""
spver=""
pdver=""
fi
# We can have a tight coupling with python-suitesparse-graphblas.
# That is, we don't need to support versions of it that are two years old.
# But, it's still useful for us to test with different versions!
psg=""
if [[ ${{ steps.sourcetype.outputs.selected}} == "upstream" ]] ; then
# Upstream needs to build with numpy 2
psgver=""
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.13') }} == true ]]; then
npver=$(python -c 'import random ; print(random.choice(["=2.1", "=2.2", ""]))')
else
npver=$(python -c 'import random ; print(random.choice(["=2.0", "=2.1", "=2.2", ""]))')
fi
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.13') }} == true ]] ; then
if [[ ${{ steps.sourcetype.outputs.selected}} == "conda-forge" ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["=9.3.1.0", "=9.4.5.0", ""]))')
psg=python-suitesparse-graphblas${psgver}
else
psgver=$(python -c 'import random ; print(random.choice(["==9.3.1.0", "==9.4.5.0", ""]))')
fi
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.12') }} == true ]] ; then
if [[ ${{ steps.sourcetype.outputs.selected}} == "conda-forge" ]] ; then
if [[ $npver == =1.* ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["=8.2.0.1", "=8.2.1.0"]))')
else
psgver=$(python -c 'import random ; print(random.choice(["=9.3.1.0", "=9.4.5.0", ""]))')
fi
psg=python-suitesparse-graphblas${psgver}
else
if [[ $npver == =1.* ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["==8.2.0.1", "==8.2.1.0"]))')
else
psgver=$(python -c 'import random ; print(random.choice(["==9.3.1.0", "==9.4.5.0", ""]))')
fi
fi
# python-suitsparse-graphblas support is the same for Python 3.10 and 3.11
elif [[ ${{ steps.sourcetype.outputs.selected}} == "conda-forge" ]] ; then
if [[ $npver == =1.* ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["=7.4.0", "=7.4.1", "=7.4.2", "=7.4.3.0", "=7.4.3.1", "=7.4.3.2", "=8.0.2.1", "=8.2.0.1", "=8.2.1.0"]))')
else
psgver=$(python -c 'import random ; print(random.choice(["=9.3.1.0", "=9.4.5.0", ""]))')
fi
psg=python-suitesparse-graphblas${psgver}
elif [[ ${{ steps.sourcetype.outputs.selected}} == "wheel" ]] ; then
if [[ $npver == =1.* ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["==7.4.3.2", "==8.0.2.1", "==8.2.0.1", "==8.2.1.0"]))')
else
psgver=$(python -c 'import random ; print(random.choice(["==9.3.1.0", "==9.4.5.0", ""]))')
fi
elif [[ ${{ steps.sourcetype.outputs.selected}} == "source" ]] ; then
# These should be exact versions
if [[ $npver == =1.* ]] ; then
psgver=$(python -c 'import random ; print(random.choice(["==7.4.0.0", "==7.4.1.0", "==7.4.2.0", "==7.4.3.0", "==7.4.3.1", "==7.4.3.2", "==8.0.2.1", "==8.2.0.1", "==8.2.1.0"]))')
else
psgver=$(python -c 'import random ; print(random.choice(["==9.3.1.0", "==9.4.5.0", ""]))')
fi
fi
# Numba is tightly coupled to numpy versions
if [[ ${npver} == "=1.26" ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.58", "=0.59", "=0.60", "=0.61", ""]))')
if [[ ${spver} == "=1.9" ]] ; then
spver=$(python -c 'import random ; print(random.choice(["=1.10", "=1.11", ""]))')
fi
elif [[ ${npver} == "=1.25" ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.58", "=0.59", "=0.60", "=0.61", ""]))')
elif [[ ${npver} == "=1.24" || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.57", "=0.58", "=0.59", "=0.60", "=0.61", ""]))')
else
numbaver=""
fi
# Only numba >=0.59 support Python 3.12
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.12') }} == true ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.59", "=0.60", "=0.61", ""]))')
fi
# Handle NumPy 2
if [[ $npver != =1.* ]] ; then
# Only pandas >=2.2.2 supports NumPy 2
pdver=$(python -c 'import random ; print(random.choice(["=2.2", ""]))')
# Only awkward >=2.6.3 supports NumPy 2
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.13') }} == true ]] ; then
akver=$(python -c 'import random ; print(random.choice(["=2.7", ""]))')
else
akver=$(python -c 'import random ; print(random.choice(["=2.6", "=2.7", ""]))')
fi
# Only scipy >=1.13 supports NumPy 2
if [[ $spver == "=1.9" || $spver == "=1.10" || $spver == "=1.11" || $spver == "=1.12" ]] ; then
spver="=1.13"
fi
fi
fmm=fast_matrix_market${fmmver}
awkward=awkward${akver}
# Don't install numba and sparse for some versions
if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') ||
startsWith(steps.pyver.outputs.selected, '3.14') }} == true ||
( ${{ matrix.slowtask != 'notebooks'}} == true && (
( ${{ matrix.os == 'windows-latest' }} == true && $(python -c 'import random ; print(random.random() < .2)') == True ) ||
( ${{ matrix.os == 'windows-latest' }} == false && $(python -c 'import random ; print(random.random() < .4)') == True ))) ]]
then
# Some packages aren't available for pypy or Python 3.13; randomly otherwise (if not running notebooks)
echo "skipping numba"
numba=""
numbaver=NA
sparse=""
sparsever=NA
if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} ]]; then
awkward=""
akver=NA
fmm=""
fmmver=NA
# Be more flexible until we determine what versions are supported by pypy
npver=""
spver=""
pdver=""
yamlver=""
fi
elif [[ ${npver} == =2.* ]] ; then
# Don't install numba for unsupported versions of numpy
numba=""
numbaver=NA
sparse=""
sparsever=NA
else
numba=numba${numbaver}
sparse=sparse${sparsever}
fi
# sparse does not yet support Python 3.13
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.13') }} == true ]] ; then
sparse=""
sparsever=NA
fi
# fast_matrix_market does not yet support Python 3.13 or osx-arm64
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.13') }} == true ||
${{ matrix.os == 'macos-latest' }} == true ]]
then
fmm=""
fmmver=NA
fi
echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psg${psgver}"
set -x # echo on
$(command -v mamba || command -v conda) install -c nodefaults \
packaging pytest coverage pytest-randomly cffi donfig tomli c-compiler make \
pyyaml${yamlver} ${sparse} pandas${pdver} scipy${spver} numpy${npver} ${awkward} \
networkx${nxver} ${numba} ${fmm} ${psg} \
${{ matrix.slowtask == 'pytest_bizarro' && 'black' || '' }} \
${{ matrix.slowtask == 'notebooks' && 'matplotlib nbconvert jupyter "ipython>=7" drawsvg' || '' }} \
${{ steps.sourcetype.outputs.selected == 'upstream' && 'cython' || '' }} \
${{ steps.sourcetype.outputs.selected != 'wheel' && '"graphblas>=7.4,<9.5"' || '' }} \
${{ contains(steps.pyver.outputs.selected, 'pypy') && 'pypy' || '' }} \
${{ matrix.os == 'windows-latest' && 'cmake' || 'm4' }} \
# ${{ matrix.os != 'windows-latest' && 'pytest-forked' || '' }} # to investigate crashes
- name: Build extension module
run: |
if [[ ${{ steps.sourcetype.outputs.selected }} == "wheel" ]]; then
# Add --pre if installing a pre-release
pip install --no-deps --only-binary ":all:" suitesparse-graphblas${psgver}
# Add the below line to the conda install command above if installing from test.pypi.org
# ${{ steps.sourcetype.outputs.selected == 'wheel' && 'setuptools setuptools-git-versioning wheel cython' || '' }} \
# pip install --no-deps --only-binary ":all:" --index-url https://test.pypi.org/simple/ "suitesparse-graphblas>=7.4.3"
elif [[ ${{ steps.sourcetype.outputs.selected }} == "source" ]]; then
# Add --pre if installing a pre-release
pip install --no-deps --no-binary suitesparse-graphblas suitesparse-graphblas${psgver}
# Add the below line to the conda install command above if installing from test.pypi.org
# ${{ steps.sourcetype.outputs.selected == 'source' && 'setuptools setuptools-git-versioning wheel cython' || '' }} \
# pip install --no-deps --no-build-isolation --no-binary suitesparse-graphblas --index-url https://test.pypi.org/simple/ suitesparse-graphblas==7.4.3.3
elif [[ ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then
pip install --no-deps git+https://github.com/GraphBLAS/python-suitesparse-graphblas.git@main#egg=suitesparse-graphblas
fi
pip install --no-deps -e .
- name: python-suitesparse-graphblas tests
run: |
# Don't use our conftest.py ; allow `test_print_jit_config` to fail if it doesn't exist
(cd ..
pytest --pyargs suitesparse_graphblas -s -k test_print_jit_config || true
pytest -v --pyargs suitesparse_graphblas || true)
- name: Print platform and sysconfig variables
run: |
python -c "import platform ; print(platform.uname())"
python -c "import pprint, sysconfig ; pprint.pprint(sysconfig.get_config_vars())"
- name: Unit tests
run: |
A=${{ needs.rngs.outputs.mapnumpy == 'A' || '' }} ; B=${{ needs.rngs.outputs.mapnumpy == 'B' || '' }}
C=${{ needs.rngs.outputs.mapnumpy == 'C' || '' }} ; D=${{ needs.rngs.outputs.mapnumpy == 'D' || '' }}
E=${{ needs.rngs.outputs.backend == 'E' || '' }} ; F=${{ needs.rngs.outputs.backend == 'F' || '' }}
G=${{ needs.rngs.outputs.backend == 'G' || '' }} ; H=${{ needs.rngs.outputs.backend == 'H' || '' }}
normal=${{ matrix.slowtask == 'pytest_normal' || '' }} ; bizarro=${{ matrix.slowtask == 'pytest_bizarro' || '' }}
ubuntu=${{ matrix.os == 'ubuntu-latest' || '' }} ; windows=${{ matrix.os == 'windows-latest' || '' }} ; macos=${{ matrix.os == 'macos-latest' || '' }}
mapnumpy='--mapnumpy' ; nomapnumpy='--no-mapnumpy' ; suitesparse='--backend=suitesparse' ; vanilla='--backend=suitesparse-vanilla'
args=$(
if [[ $A && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $A && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $B && $normal ]] ; then if [[ $macos ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $B && $bizarro ]] ; then if [[ $macos ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $C && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $C && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $D && $normal ]] ; then if [[ $macos ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $D && $bizarro ]] ; then if [[ $macos ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $E && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $E && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $F && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $F && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $G && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $G && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)
echo ${args}
set -x # echo on
# pytest ${{ matrix.os != 'windows-latest' && '--forked' || '' }} \ # to investigate crashes
# --color=yes --randomly -v -s ${args} \
coverage run -m pytest --color=yes --randomly -v ${args} \
${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }}
- name: Unit tests (bizarro scalars)
run: |
# Run tests again with Scalars being C scalars by default
find graphblas -type f -name "*.py" -print0 | xargs -0 sed -i -s \
-e '/# pragma: is_grbscalar/! s/is_cscalar=False/is_cscalar=True/g' \
-e '/# pragma: is_grbscalar/! s/is_cscalar = False/is_cscalar = True/g' \
-e '/# pragma: to_grb/ s/is_cscalar=True/is_cscalar=False/g' \
-e '/# pragma: to_grb/ s/is_cscalar = True/is_cscalar = False/g'
A=${{ needs.rngs.outputs.mapnumpy == 'A' || '' }} ; B=${{ needs.rngs.outputs.mapnumpy == 'B' || '' }}
C=${{ needs.rngs.outputs.mapnumpy == 'C' || '' }} ; D=${{ needs.rngs.outputs.mapnumpy == 'D' || '' }}
E=${{ needs.rngs.outputs.backend == 'E' || '' }} ; F=${{ needs.rngs.outputs.backend == 'F' || '' }}
G=${{ needs.rngs.outputs.backend == 'G' || '' }} ; H=${{ needs.rngs.outputs.backend == 'H' || '' }}
normal=${{ matrix.slowtask == 'pytest_normal' || '' }} ; bizarro=${{ matrix.slowtask == 'pytest_bizarro' || '' }}
ubuntu=${{ matrix.os == 'ubuntu-latest' || '' }} ; windows=${{ matrix.os == 'windows-latest' || '' }} ; macos=${{ matrix.os == 'macos-latest' || '' }}
mapnumpy='--mapnumpy' ; nomapnumpy='--no-mapnumpy' ; suitesparse='--backend=suitesparse' ; vanilla='--backend=suitesparse-vanilla'
args=$(
if [[ $A && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $A && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $B && $normal ]] ; then if [[ $macos ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $B && $bizarro ]] ; then if [[ $macos ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $C && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $C && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $D && $normal ]] ; then if [[ $macos ]] ; then echo " $mapnumpy" ; elif [[ $windows ]] ; then echo " $nomapnumpy" ; fi ; fi)$( \
if [[ $D && $bizarro ]] ; then if [[ $macos ]] ; then echo " $nomapnumpy" ; elif [[ $windows ]] ; then echo " $mapnumpy" ; fi ; fi)$( \
if [[ $E && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $E && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $F && $normal ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $F && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $G && $normal ]] ; then if [[ $ubuntu ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $G && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \
if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \
if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)
echo ${args}
set -x # echo on
# pytest ${{ matrix.os != 'windows-latest' && '--forked' || '' }} \ # to investigate crashes
# --color=yes --randomly -v -s ${args} \
coverage run -a -m pytest --color=yes --randomly -v ${args} \
${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }}
git checkout . # Undo changes to scalar default
- name: Miscellaneous tests
if: matrix.slowtask == 'pytest_normal'
run: |
# Test (and cover) automatic initialization
coverage run -a graphblas/tests/test_auto_init.py
coverage run -a graphblas/tests/test_external_init.py
# Test (and cover) lazy module loader
echo "from graphblas.agg import count" > script.py
coverage run -a script.py
echo "from graphblas import agg" > script.py # Does this still cover?
echo "from graphblas.core.operator import agg" >> script.py
coverage run -a script.py
# Tests lazy loading of lib, ffi, and NULL in gb.core
echo "from graphblas.core import base" > script.py
coverage run -a script.py
# Test another code pathway for loading lib
echo "from graphblas.core import lib" > script.py
coverage run -a script.py
rm script.py
# Tests whose coverage depend on order of tests :/
# TODO: understand why these are order-dependent and try to fix
coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py
# coverage run -a -m pytest --color=yes -x --no-mapnumpy -k test_npmonoid graphblas/tests/test_numpyops.py --runslow
- name: More tests for coverage
if: matrix.slowtask == 'notebooks' && matrix.os == 'windows-latest'
run: |
# We use 'notebooks' slow task b/c it should have numba installed
coverage run -a -m pytest --color=yes --runslow --no-mapnumpy -p no:randomly -v -k 'test_commutes or test_bool_doesnt_get_too_large or test_npbinary or test_npmonoid or test_npsemiring'
coverage run -a -m pytest --color=yes --runslow --mapnumpy -p no:randomly -k 'test_bool_doesnt_get_too_large or test_npunary or test_binaryop_monoid_numpy'
coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py
- name: Auto-generated code check
if: matrix.slowtask == 'pytest_bizarro'
run: |
# This step uses `black`
coverage run -a -m graphblas.core.automethods
coverage run -a -m graphblas.core.infixmethods
git diff --exit-code
- name: Coverage
run: |
coverage xml
coverage report --show-missing
- name: codecov
uses: codecov/codecov-action@v5
- name: Notebooks Execution check
if: matrix.slowtask == 'notebooks'
run: |
# Run notebooks only if numba is installed
if python -c 'import numba' 2> /dev/null ; then
jupyter nbconvert --to notebook --execute notebooks/*ipynb
fi