Skip to content
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

BUG: sparse: raise error for array classes, document/test old behavior #20490

Merged
merged 9 commits into from
May 7, 2024
10 changes: 9 additions & 1 deletion scipy/sparse/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,15 @@ def getrow(self, i):

class sparray:
"""A namespace class to separate sparray from spmatrix"""
pass


def __init__(self, *args, **kwargs):
if np.isscalar(args[0]):
raise ValueError(
"scipy sparse array classes do not \
support instantiation from a scalar"
ilan-gold marked this conversation as resolved.
Show resolved Hide resolved
)
super().__init__(*args, **kwargs)
Copy link
Contributor

@dschult dschult Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __init__ methods are pretty spread out across classes already. If it spreads more it may become hard to tell which init methods gets called during the init process. So, I think in the long run this check might be better placed inside _sputils.check_shape. But that's just my suggestion. I'm ok with other choices.

@perimosocordiae should probably decide.


sparray.__doc__ = _spbase.__doc__

Expand Down
8 changes: 5 additions & 3 deletions scipy/sparse/_bsr.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ def __init__(self, arg1, shape=None, dtype=None, copy=False, blocksize=None):
if not isshape(blocksize):
raise ValueError(f'invalid blocksize={blocksize}')
if tuple(blocksize) != self.data.shape[1:]:
raise ValueError('mismatching blocksize={} vs {}'.format(
blocksize, self.data.shape[1:]))
raise ValueError(
f'mismatching blocksize={blocksize} \
vs {self.data.shape[1:]}'
ilan-gold marked this conversation as resolved.
Show resolved Hide resolved
)
else:
raise ValueError('unrecognized bsr_array constructor usage')
else:
Expand Down Expand Up @@ -640,7 +642,7 @@ def isspmatrix_bsr(x):


# This namespace class separates array from matrix with isinstance
class bsr_array(_bsr_base, sparray):
class bsr_array(sparray, _bsr_base):
"""
Block Sparse Row format sparse array.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_coo.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ def isspmatrix_coo(x):


# This namespace class separates array from matrix with isinstance
class coo_array(_coo_base, sparray):
class coo_array(sparray, _coo_base):
"""
A sparse array in COOrdinate format.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_csc.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def isspmatrix_csc(x):


# This namespace class separates array from matrix with isinstance
class csc_array(_csc_base, sparray):
class csc_array(sparray, _csc_base):
"""
Compressed Sparse Column array.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def isspmatrix_csr(x):


# This namespace class separates array from matrix with isinstance
class csr_array(_csr_base, sparray):
class csr_array(sparray, _csr_base):
"""
Compressed Sparse Row array.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_dia.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ def isspmatrix_dia(x):


# This namespace class separates array from matrix with isinstance
class dia_array(_dia_base, sparray):
class dia_array(sparray, _dia_base):
"""
Sparse array with DIAgonal storage.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_dok.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ def isspmatrix_dok(x):


# This namespace class separates array from matrix with isinstance
class dok_array(_dok_base, sparray):
class dok_array(sparray, _dok_base):
"""
Dictionary Of Keys based sparse array.

Expand Down
2 changes: 1 addition & 1 deletion scipy/sparse/_lil.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ def isspmatrix_lil(x):


# This namespace class separates array from matrix with isinstance
class lil_array(_lil_base, sparray):
class lil_array(sparray, _lil_base):
"""
Row-based LIst of Lists sparse array.

Expand Down
33 changes: 32 additions & 1 deletion scipy/sparse/tests/test_construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@

from scipy.sparse import (csr_matrix, coo_matrix,
csr_array, coo_array,
sparray, spmatrix,
csc_array, bsr_array,
dia_array, dok_array,
lil_array, csc_matrix,
bsr_matrix, dia_matrix,
lil_matrix, sparray, spmatrix,
_construct as construct)
from scipy.sparse._construct import rand as sprand

Expand All @@ -37,6 +41,33 @@ def _sprandn_array(m, n, density=0.01, format="coo", dtype=None, random_state=No


class TestConstructUtils:

@pytest.mark.parametrize("cls", [
csc_array, csr_array, coo_array, bsr_array,
dia_array, dok_array, lil_array
])
def test_singleton_array_constructor(self, cls):
with pytest.raises(
ValueError,
match='scipy sparse array classes do not \
support instantiation from a scalar'
ilan-gold marked this conversation as resolved.
Show resolved Hide resolved
):
cls(0)

@pytest.mark.parametrize("cls", [
csc_matrix, csr_matrix, coo_matrix,
bsr_matrix, dia_matrix, lil_matrix
])
def test_singleton_matrix_constructor(self, cls):
"""
This test is for backwards compatibility post scipy 1.13.
The behavior observed here is what is to be expected
with the older matrix classes. This test comes with the
exception of dok_matrix, which was not working pre scipy1.12
(unlike the rest of these).
"""
assert cls(0).shape == (1, 1)

def test_spdiags(self):
diags1 = array([[1, 2, 3, 4, 5]])
diags2 = array([[1, 2, 3, 4, 5],
Expand Down