Skip to content

Commit

Permalink
Support sparse 0.13 and expand tests on Python 3.7
Browse files Browse the repository at this point in the history
* specify torch >=2
* test against any available wheel on each supported Python version
* make pytest run regardless of what optional packages installed
  • Loading branch information
alugowski committed Oct 26, 2023
1 parent b35a909 commit e021256
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 54 deletions.
38 changes: 21 additions & 17 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,48 +22,52 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Install base dependencies
run: pip install tabulate pytest
run: pip install tabulate pytest pytest-subtests html5lib

- name: Test minimums
run: pytest tests/test_basic.py tests/test_list_like.py

- name: Install test dependencies
if: ${{ !contains(matrix.python-version, 'pypy') }} # no scipy wheels for pypy
run: pip install pytest pytest-subtests html5lib scipy
- name: Install NumPy and SciPy
run: |
pip install --only-binary ":all:" numpy
pip install --only-binary ":all:" scipy || true
- name: Python only scipy
if: ${{ !contains(matrix.python-version, 'pypy') }} # no scipy wheels for pypy
- name: Test only SciPy
run: pytest

- name: Install other supported packages
if: ${{ !contains(matrix.python-version, 'pypy') && matrix.python-version != '3.7' }} # no wheels for pypy and old python
run: |
pip install suitesparse-graphblas==7.4.4.1a1
pip install python-graphblas
pip install sparse
pip install torch
pip install tensorflow
echo "=== Install Python-graphblas =================="
pip install --only-binary ":all:" python-graphblas || true
echo ""
echo "=== Install PyData/Sparse ====================="
pip install --only-binary ":all:" sparse || true
echo ""
echo "=== Install PyTorch ==========================="
pip install --only-binary ":all:" "torch>=2.0.0" || true
echo ""
echo "=== Install TensorFlow ========================="
pip install --only-binary ":all:" tensorflow || true
- name: Python Test without Jupyter
if: ${{ !contains(matrix.python-version, 'pypy') }} # no scipy wheels for pypy
run: pytest

- name: Install Jupyter
if: ${{ !contains(matrix.python-version, 'pypy') }} # no scipy wheels for pypy
if: ${{ !contains(matrix.python-version, 'pypy') }}
run: pip install jupyter

- name: Python Test with Jupyter
if: ${{ !contains(matrix.python-version, 'pypy') }} # no scipy wheels for pypy
if: ${{ !contains(matrix.python-version, 'pypy') }}
run: pytest

- name: Python Test with Coverage
if: ${{ contains(matrix.os, 'ubuntu') && !contains(matrix.python-version, 'pypy') }}
if: ${{ contains(matrix.os, 'ubuntu') }}
run: |
pip install pytest-cov
pytest --cov=matrepr --cov-report term --cov-report=xml
- name: Upload Coverage to Codecov
if: ${{ contains(matrix.os, 'ubuntu') && !contains(matrix.python-version, 'pypy') }}
if: ${{ contains(matrix.os, 'ubuntu') }}
uses: codecov/codecov-action@v3
with:
gcov: true
Expand Down
7 changes: 6 additions & 1 deletion matrepr/adapters/sparse_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ def describe(self) -> str:
if hasattr(self.mat, "nbytes"):
parts.append(sizeof_fmt(self.mat.nbytes))

try:
fmt = self.mat.format
except AttributeError:
fmt = self.mat.__class__.__name__

Check warning on line 43 in matrepr/adapters/sparse_impl.py

View check run for this annotation

Codecov / codecov/patch

matrepr/adapters/sparse_impl.py#L40-L43

Added lines #L40 - L43 were not covered by tests

return describe(shape=self.mat.shape,
nnz=self.mat.nnz, nz_type=self.mat.dtype,
layout=self.mat.format,
layout=fmt,
notes=", ".join(parts))


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ repository = "https://github.com/alugowski/matrepr"

[project.optional-dependencies]
test = ["pytest", "html5lib", "scipy"]
supported = ["scipy", "numpy", "python-graphblas", "sparse", "torch", "tensorflow"]
supported = ["scipy", "numpy", "python-graphblas", "sparse", "torch>=2.0.0", "tensorflow"]
9 changes: 3 additions & 6 deletions tests/test_graphblas.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@

# Context initialization must happen before any other imports
gb.init("suitesparse", blocking=False)

have_gb = True
except ImportError:
have_gb = False
gb = None


Expand All @@ -34,7 +31,7 @@ def generate_fixed_value(m, n):
return gb.Matrix.from_coo(rows, cols, data, nrows=m, ncols=n, dtype='int64'), data


@unittest.skipIf(not have_gb, "python-graphblas not installed")
@unittest.skipIf(not gb, "python-graphblas not installed")
class GraphBLASMatrixTests(unittest.TestCase):
def setUp(self):
mat = gb.Matrix.from_coo([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], nrows=5, ncols=5)
Expand Down Expand Up @@ -81,7 +78,7 @@ def test_truncate(self):
self.assertEqual(expected_count, count)


@unittest.skipIf(not have_gb, "python-graphblas not installed")
@unittest.skipIf(not gb, "python-graphblas not installed")
class GraphBLASVectorTests(unittest.TestCase):
def setUp(self):
vec = gb.Vector.from_coo([0, 3, 4, 6], [12.1, -5.4, 2.9, 2.2], size=8)
Expand Down Expand Up @@ -121,7 +118,7 @@ def test_truncate(self):
self.assertIn(f"<td>{value}</td>", res)


@unittest.skipIf(not have_gb, "python-graphblas not installed")
@unittest.skipIf(not gb, "python-graphblas not installed")
class PatchGraphBLASTests(unittest.TestCase):
def test_patch_graphblas(self):
mat = gb.Matrix.from_coo([0, 1], [0, 1], [111, 222], nrows=5, ncols=5),
Expand Down
14 changes: 10 additions & 4 deletions tests/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
import unittest

import html5lib
import numpy.random
import scipy.sparse
try:
import scipy
import scipy.sparse

from matrepr import to_html
import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

numpy.random.seed(123)
from matrepr import to_html


def generate_fixed_value(m, n):
Expand All @@ -28,6 +33,7 @@ def generate_fixed_value(m, n):
return scipy.sparse.coo_matrix((data, (rows, cols)), shape=(m, n), dtype='int64')


@unittest.skipIf(scipy is None, "scipy not installed")
class ToHTMLTests(unittest.TestCase):
def setUp(self):
self.mats = [
Expand Down
14 changes: 10 additions & 4 deletions tests/test_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

import unittest

import numpy.random
import scipy.sparse
try:
import scipy
import scipy.sparse

from matrepr import to_latex
import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

numpy.random.seed(123)
from matrepr import to_latex


def generate_fixed_value(m, n):
Expand All @@ -26,6 +31,7 @@ def generate_fixed_value(m, n):
return scipy.sparse.coo_matrix((data, (rows, cols)), shape=(m, n), dtype='int64')


@unittest.skipIf(scipy is None, "scipy not installed")
class ToLatexTests(unittest.TestCase):
def setUp(self):
self.mats = [
Expand Down
10 changes: 7 additions & 3 deletions tests/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@

import unittest

import numpy as np
try:
import numpy as np

from matrepr import to_html, to_latex, to_str
np.random.seed(123)
except ImportError:
np = None

np.random.seed(123)
from matrepr import to_html, to_latex, to_str


@unittest.skipIf(np is None, "numpy not installed")
class NumpyTests(unittest.TestCase):
def setUp(self):
self.mats = [
Expand Down
14 changes: 10 additions & 4 deletions tests/test_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
import unittest
import time

import numpy.random
import scipy.sparse
try:
import scipy
import scipy.sparse

from matrepr import to_html
import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

numpy.random.seed(123)
from matrepr import to_html


@unittest.skipIf(scipy is None, "scipy not installed")
class PerformanceTests(unittest.TestCase):
def test_to_html_speed(self):
# warmup, just in case
Expand Down
15 changes: 11 additions & 4 deletions tests/test_scipy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

import unittest

import numpy.random
import scipy.sparse
try:
import scipy
import scipy.sparse

from matrepr import to_html, to_latex, to_str
import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

numpy.random.seed(123)
from matrepr import to_html, to_latex, to_str


def generate_fixed_value(m, n):
Expand All @@ -26,6 +31,7 @@ def generate_fixed_value(m, n):
return scipy.sparse.coo_matrix((data, (rows, cols)), shape=(m, n), dtype='int64')


@unittest.skipIf(scipy is None, "scipy not installed")
class SciPyTests(unittest.TestCase):
def setUp(self):
self.mats = [
Expand Down Expand Up @@ -66,6 +72,7 @@ def test_formats(self):
self.assertEqual(expected[i], res)


@unittest.skipIf(scipy is None, "scipy not installed")
class PatchSciPyTests(unittest.TestCase):
def test_patch_scipy(self):
source_mat = scipy.sparse.coo_matrix(([111, 222], ([0, 1], [0, 1])), shape=(10, 10))
Expand Down
21 changes: 16 additions & 5 deletions tests/test_sparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@
except ImportError:
sparse = None

from matrepr import to_html, to_latex, to_str
try:
import scipy
import scipy.sparse

import scipy
import numpy as np
np.random.seed(123)
import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

from matrepr import to_html, to_latex, to_str


def generate_fixed_value(m, n):
Expand All @@ -39,10 +45,13 @@ def setUp(self):
sparse.COO(coords=np.array([1, 4]), data=np.array([11, 44]), shape=(10,)),
sparse.COO(np.empty(shape=(10, 10))),
sparse.random((10, 10), density=0.4),
sparse.COO.from_scipy_sparse(generate_fixed_value(10, 10)),
sparse.COO(coords=np.array([[0, 0], [0, 0]]), data=np.array([111, 222]), shape=(13, 13)), # has dupes
sparse.COO(coords=np.array([[0, 1], [3, 2], [1, 3]]), data=np.array([111, 222]), shape=(5, 5, 5)),
]
if scipy is not None:
self.mats.append(
sparse.COO.from_scipy_sparse(generate_fixed_value(10, 10))
)

with warnings.catch_warnings():
# COO will incorrectly complain that the object is not ndarray when it is.
Expand Down Expand Up @@ -103,13 +112,15 @@ def test_truncate_1d(self):
for value in [1000, 1009]:
self.assertIn(f"<td>{value}</td>", res)

@unittest.skipIf(scipy is None, "scipy not installed")
def test_contents_2d(self):
mat = generate_fixed_value(10, 10)
sparse_mat = sparse.COO.from_scipy_sparse(mat)
res = to_html(sparse_mat, notebook=False, max_rows=20, max_cols=20, title=True, indices=True)
for value in mat.data:
self.assertIn(f"<td>{value}</td>", res)

@unittest.skipIf(scipy is None, "scipy not installed")
def test_truncate_2d(self):
mat = generate_fixed_value(20, 20)
sparse_mat = sparse.COO.from_scipy_sparse(mat)
Expand Down
11 changes: 10 additions & 1 deletion tests/test_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@

import unittest

import scipy.sparse
try:
import scipy
import scipy.sparse

import numpy.random
numpy.random.seed(123)
except ImportError:
scipy = None
numpy = None

from matrepr import to_str
from matrepr.string_formatter import max_line_width
Expand All @@ -24,6 +32,7 @@ def generate_fixed_value(m, n):
return scipy.sparse.coo_matrix((data, (rows, cols)), shape=(m, n), dtype='int64')


@unittest.skipIf(scipy is None, "scipy not installed")
class ToStrTests(unittest.TestCase):
def setUp(self):
self.mats = [
Expand Down
8 changes: 4 additions & 4 deletions tests/test_torch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
import unittest
import warnings

import numpy as np

try:
import torch

import numpy.random
numpy.random.seed(123)
except ImportError:
torch = None
numpy = None

from matrepr import to_html, to_latex, to_str

np.random.seed(123)


def generate_fixed_value(m, n):
row_factor = 10**(1+len(str(n)))
Expand Down

0 comments on commit e021256

Please sign in to comment.