Thanks to visit codestin.com
Credit goes to github.com

Skip to content

making numba optional #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8243013
WIP: making numba optional
eriknw Apr 3, 2023
a987553
No numba on Python 3.11; use conda
eriknw Apr 4, 2023
d31b3de
skip notebooks and try mamba
eriknw Apr 4, 2023
9c6bb51
Only test pypy
eriknw Apr 4, 2023
02d261c
bump pandas 2.0.0
eriknw Apr 4, 2023
61f5660
Don't test against pypy in CI
eriknw Apr 4, 2023
71af5e7
Update classifiers (we don't officially support PyPy)
eriknw Apr 4, 2023
6200a9f
expand optional dependencies
eriknw Apr 5, 2023
d4ae208
networkx 3.1
eriknw Apr 5, 2023
21ddb7f
simplify/combine deps
eriknw Apr 5, 2023
3af869c
Make suitesparse_graphblas optional (in the future); don't install nu…
eriknw Apr 7, 2023
5cdaa31
Test numba 0.57.0rc1
eriknw Apr 7, 2023
78c2666
oops
eriknw Apr 7, 2023
ce0a667
Ignore deprecation warning raised by awkward in Python 3.11
eriknw Apr 7, 2023
0b6dcaf
try to ignore warning from sparse
eriknw Apr 7, 2023
67a5b71
drop sparse 0.12 (which is really old and annoying to support)
eriknw Apr 7, 2023
0f66e65
sre_constants also deprecated
eriknw Apr 7, 2023
fd82c12
clean up
eriknw Apr 7, 2023
ccb1b30
`shouldhave` make tests a little more clear (I think)
eriknw Apr 9, 2023
e1ed1f0
Recipes for L1norm and Linfnorm aggregators
eriknw Apr 9, 2023
a074aa0
Better error message for default operators that are UDFs
eriknw Apr 9, 2023
b9f221f
Update isclose recipe
eriknw Apr 9, 2023
ad0d858
Get ready to merge
eriknw Apr 12, 2023
de2c81f
Try this
eriknw Apr 12, 2023
837796c
Stress test numba 0.57.0rc1 on Windows
eriknw Apr 12, 2023
571b27a
But which unaryop is causing this?!
eriknw Apr 12, 2023
30f5532
more debug print
eriknw Apr 13, 2023
3f4a3ee
Always test with numpy 1.24
eriknw Apr 13, 2023
050d709
Don't map numpy
eriknw Apr 13, 2023
73205e8
more brutal testing
eriknw Apr 13, 2023
cc08a34
forgot a `-s`
eriknw Apr 13, 2023
4c7441b
shuffle attrs
eriknw Apr 13, 2023
4b0c3cb
where exactly does it happen? also, only wheels for psg
eriknw Apr 13, 2023
bb35f98
relax numpy version
eriknw Apr 13, 2023
f4645ce
exp2 reliably fails; what else?
eriknw Apr 13, 2023
e7422a5
test
eriknw Apr 13, 2023
92c8df5
Try other sources of psg
eriknw Apr 13, 2023
757ea24
undo testing numba on windows
eriknw Apr 13, 2023
3db0f4e
numba version depends on python and numpy versions
eriknw Apr 13, 2023
2e9d8cd
coverage
eriknw Apr 14, 2023
e6f94ec
lazy indexunary handling and a bit more coverage
eriknw Apr 15, 2023
eb1560e
skip numba 0.57.0rc1 on Windows for now
eriknw Apr 16, 2023
f6f35d2
quick experiment with coverage
eriknw Apr 16, 2023
49e29f8
try "no branch" here
eriknw Apr 16, 2023
759405f
coverage cleanup
eriknw Apr 16, 2023
945bdf9
Merge branch 'main' into no_numba
eriknw Apr 16, 2023
f6c6d27
Make PNGs smaller via https://tinypng.com
eriknw Apr 16, 2023
10706aa
mark a couple more lines as flaky coverage
eriknw Apr 16, 2023
789a37e
Two more flaky coverage
eriknw Apr 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions .github/workflows/imports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@ on:
- main

jobs:
test_imports:
rngs:
runs-on: ubuntu-latest
# strategy:
# matrix:
# python-version: ["3.8", "3.9", "3.10"]
outputs:
os: ${{ steps.os.outputs.selected }}
pyver: ${{ steps.pyver.outputs.selected }}
steps:
- uses: actions/checkout@v3
- name: RNG for os
uses: ddradar/[email protected]
id: os
with:
contents: |
ubuntu-latest
macos-latest
windows-latest
weights: |
1
1
1
- name: RNG for Python version
uses: ddradar/[email protected]
id: pyver
Expand All @@ -22,14 +33,26 @@ jobs:
3.8
3.9
3.10
3.11
weights: |
1
1
1
1
test_imports:
needs: rngs
runs-on: ${{ needs.rngs.outputs.os }}
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# python-version: ["3.8", "3.9", "3.10", "3.11"]
# os: ["ubuntu-latest", "macos-latest", "windows-latest"]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ steps.pyver.outputs.selected }}
python-version: ${{ needs.rngs.outputs.pyver }}
# python-version: ${{ matrix.python-version }}
- run: python -m pip install --upgrade pip
- run: pip install -e .
- run: pip install -e .[default]
- run: ./scripts/test_imports.sh
105 changes: 78 additions & 27 deletions .github/workflows/test_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,19 @@ jobs:
id: pyver
with:
# We should support major Python versions for at least 36-42 months
# We could probably support pypy if numba were optional
# We may be able to support pypy if anybody asks for it
# 3.8.16 0_73_pypy
# 3.9.16 0_73_pypy
contents: |
3.8
3.9
3.10
3.11
weights: |
1
1
1
1
- name: RNG for source of python-suitesparse-graphblas
uses: ddradar/[email protected]
id: sourcetype
Expand All @@ -138,8 +140,8 @@ jobs:
miniforge-version: latest
use-mamba: true
python-version: ${{ steps.pyver.outputs.selected }}
channels: conda-forge,nodefaults
channel-priority: strict
channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }}
channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }}
activate-environment: graphblas
auto-activate-base: false
- name: Setup conda
Expand All @@ -150,8 +152,8 @@ jobs:
with:
auto-update-conda: true
python-version: ${{ steps.pyver.outputs.selected }}
channels: conda-forge,nodefaults
channel-priority: strict
channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }}
channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }}
activate-environment: graphblas
auto-activate-base: false
- name: Update env
Expand All @@ -161,29 +163,29 @@ jobs:
#
# First let's randomly get versions of dependencies to install.
# Consider removing old versions when they become problematic or very old (>=2 years).
nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", ""]))')
nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", "=3.1", ""]))')
yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))')
sparsever=$(python -c 'import random ; print(random.choice(["=0.12", "=0.13", "=0.14", ""]))')
fmmver=$(python -c 'import random ; print(random.choice(["=1.4", ""]))')
sparsever=$(python -c 'import random ; print(random.choice(["=0.13", "=0.14", ""]))')
fmmver=$(python -c 'import random ; print(random.choice(["=1.4", "=1.5", ""]))')
if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.8') }} == true ]]; then
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))')
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.9') }} == true ]]; then
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))')
elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.10') }} == true ]]; then
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.3", "=1.4", "=1.5", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.3", "=1.4", "=1.5", "=2.0", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))')
else # Python 3.11
npver=$(python -c 'import random ; print(random.choice(["=1.23", ""]))')
npver=$(python -c 'import random ; print(random.choice(["=1.23", "=1.24", ""]))')
spver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.5", ""]))')
pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))')
akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))')
fi
if [[ ${{ steps.sourcetype.outputs.selected }} == "source" || ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then
Expand All @@ -208,16 +210,54 @@ jobs:
else
psgver=""
fi
if [[ $npver == "=1.21" ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", ""]))')
# TODO: drop 0.57.0rc1 and use 0.57 once numba 0.57 is properly released
if [[ ${npver} == "=1.24" || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.57.0rc1", ""]))')
elif [[ ${npver} == "=1.21" ]] ; then
numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57.0rc1", ""]))')
else
numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))')
fi
if [[ ${{ matrix.os == 'windows-latest' }} == true && ( ${npver} == "=1.24" || ${numbaver} == "=0.57.0rc1" ) ]] ; then
# TODO: numba 0.57.0rc1 currently crashes sometimes on windows, so skip it for now
npver=""
numbaver=""
fi
fmm=fast_matrix_market${fmmver}
awkward=awkward${akver}
if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') ||
startsWith(steps.pyver.outputs.selected, '3.12') }} == 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.12; 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
else
numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))')
numba=numba${numbaver}
sparse=sparse${sparsever}
fi
echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}"

$(command -v mamba || command -v conda) install packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \
pyyaml${yamlver} sparse${sparsever} pandas${pdver} scipy${spver} numpy${npver} awkward${akver} \
networkx${nxver} numba${numbaver} fast_matrix_market${fmmver} ${psg} \
# TODO: remove `-c numba` when numba 0.57 is properly released
$(command -v mamba || command -v conda) install -c numba packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \
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"' || '' }} \
${{ steps.sourcetype.outputs.selected == 'upstream' && 'cython' || '' }} \
Expand Down Expand Up @@ -269,9 +309,9 @@ jobs:
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
echo ${args}
pytest -v --pyargs suitesparse_graphblas
coverage run -m pytest --color=yes --randomly -v $args \
coverage run -m pytest --color=yes --randomly -v ${args} \
${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }}
- name: Unit tests (bizarro scalars)
run: |
Expand Down Expand Up @@ -305,8 +345,8 @@ jobs:
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
coverage run -a -m pytest --color=yes --randomly -v $args \
echo ${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
Expand All @@ -329,6 +369,13 @@ jobs:
# 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: |
Expand Down Expand Up @@ -364,7 +411,11 @@ jobs:
uses: codecov/codecov-action@v3
- name: Notebooks Execution check
if: matrix.slowtask == 'notebooks'
run: jupyter nbconvert --to notebook --execute notebooks/*ipynb
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

finish:
needs: build_and_test
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ repos:
- id: black
- id: black-jupyter
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.260
rev: v0.0.261
hooks:
- id: ruff
args: [--fix-only, --show-fixes]
Expand Down Expand Up @@ -86,7 +86,7 @@ repos:
additional_dependencies: [tomli]
files: ^(graphblas|docs)/
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.260
rev: v0.0.261
hooks:
- id: ruff
- repo: https://github.com/sphinx-contrib/sphinx-lint
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $ conda install -c conda-forge python-graphblas
```
or pip:
```
$ pip install python-graphblas
$ pip install python-graphblas[default]
```
This will also install the [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS) compiled C library.

Expand Down
Binary file modified docs/_static/img/GraphBLAS-API-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/GraphBLAS-mapping.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/Matrix-A-strictly-upper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/Matrix-A-upper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/Recorder-output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/adj-graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/draw-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions docs/_static/img/logo-name-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions docs/_static/img/logo-name-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions docs/_static/img/logo-name-medium.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/min-plus-semiring.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/plus-times-semiring.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/repr-matrix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/repr-scalar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/repr-vector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/img/sssp-result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/getting_started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Using pip:

::

pip install python-graphblas
pip install python-graphblas[default]

Whether installing with conda or pip, the underlying package that is imported in Python
is named ``graphblas``. The convention is to import as:
Expand Down
16 changes: 15 additions & 1 deletion graphblas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,21 @@ def _init(backend_arg, blocking, automatic=False):

backend = backend_arg
if backend in {"suitesparse", "suitesparse-vanilla"}:
from suitesparse_graphblas import ffi, initialize, is_initialized, lib
try:
from suitesparse_graphblas import ffi, initialize, is_initialized, lib
except ImportError: # pragma: no cover (import)
raise ImportError(
f"suitesparse_graphblas is required for {backend!r} backend. "
"It may be installed with pip or conda:\n\n"
" $ pip install suitesparse-graphblas\n"
" $ conda install -c conda-forge python-suitesparse-graphblas\n\n"
"SuiteSparse:GraphBLAS is the primary C implementation and backend of "
"python-graphblas and is what we recommend to most users. If you are "
"installing python-graphblas with pip, we recommend installing with one "
"of the following to automatically include suitespare-graphblas:\n\n"
" $ pip install python-graphblas[suitesparse]\n"
" $ pip install python-graphblas[default]"
) from None

if is_initialized():
mode = ffi.new("int32_t*")
Expand Down
Loading