11# SPDX-License-Identifier: MPL-2.0
22from __future__ import annotations
33
4+ from importlib .metadata import version
45from importlib .util import find_spec
56from pathlib import Path
67from typing import TYPE_CHECKING , cast
910import pytest
1011import scipy .sparse as sps
1112from numpy .exceptions import AxisError
13+ from packaging .version import Version
1214
1315from fast_array_utils import stats , types
1416from testing .fast_array_utils import SUPPORTED_TYPES , Flags
3941ATS_CUPY_SPARSE = {at for at in SUPPORTED_TYPES if "cupyx.scipy" in str (at )}
4042
4143
44+ def _xfail_if_old_scipy (array_type : ArrayType [Any ], ndim : Literal [1 , 2 ]) -> pytest .MarkDecorator :
45+ cond = ndim == 1 and bool (array_type .flags & Flags .Sparse ) and Version (version ("scipy" )) < Version ("1.14" )
46+ return pytest .mark .xfail (cond , reason = "Sparse matrices don’t support 1d arrays" )
47+
48+
4249@pytest .fixture (
4350 scope = "session" ,
4451 params = [
@@ -134,7 +141,10 @@ def pbmc64k_reduced_raw() -> sps.csr_array[np.float32]:
134141@pytest .mark .array_type (skip = {* ATS_SPARSE_DS , Flags .Matrix })
135142@pytest .mark .parametrize ("func" , STAT_FUNCS )
136143@pytest .mark .parametrize (("ndim" , "axis" ), [(1 , 0 ), (2 , 3 ), (2 , - 1 )], ids = ["1d-ax0" , "2d-ax3" , "2d-axneg" ])
137- def test_ndim_error (array_type : ArrayType [Array ], func : StatFunNoDtype , ndim : Literal [1 , 2 ], axis : Literal [0 , 1 ] | None ) -> None :
144+ def test_ndim_error (
145+ request : pytest .FixtureRequest , array_type : ArrayType [Array ], func : StatFunNoDtype , ndim : Literal [1 , 2 ], axis : Literal [0 , 1 ] | None
146+ ) -> None :
147+ request .applymarker (_xfail_if_old_scipy (array_type , ndim ))
138148 check_ndim (array_type , ndim )
139149 # not using the fixture because we don’t need to test multiple dtypes
140150 np_arr = np .array ([[1 , 2 , 3 ], [4 , 5 , 6 ]], dtype = np .float32 )
@@ -148,12 +158,15 @@ def test_ndim_error(array_type: ArrayType[Array], func: StatFunNoDtype, ndim: Li
148158
149159@pytest .mark .array_type (skip = ATS_SPARSE_DS )
150160def test_sum (
161+ request : pytest .FixtureRequest ,
151162 array_type : ArrayType [CpuArray | GpuArray | DiskArray | types .DaskArray ],
152163 dtype_in : type [DTypeIn ],
153164 dtype_arg : type [DTypeOut ] | None ,
154165 axis : Literal [0 , 1 ] | None ,
155166 np_arr : NDArray [DTypeIn ],
167+ ndim : Literal [1 , 2 ],
156168) -> None :
169+ request .applymarker (_xfail_if_old_scipy (array_type , ndim ))
157170 if np .dtype (dtype_arg ).kind in "iu" and (array_type .flags & Flags .Gpu ) and (array_type .flags & Flags .Sparse ):
158171 pytest .skip ("GPU sparse matrices don’t support int dtypes" )
159172 arr = array_type (np_arr .copy ())
@@ -209,7 +222,8 @@ def test_sum_dask_shapes(array_type: ArrayType[types.DaskArray], axis: Literal[0
209222
210223
211224@pytest .mark .array_type (skip = ATS_SPARSE_DS )
212- def test_mean (array_type : ArrayType [Array ], axis : Literal [0 , 1 ] | None , np_arr : NDArray [DTypeIn ]) -> None :
225+ def test_mean (request : pytest .FixtureRequest , array_type : ArrayType [Array ], axis : Literal [0 , 1 ] | None , np_arr : NDArray [DTypeIn ], ndim : Literal [1 , 2 ]) -> None :
226+ request .applymarker (_xfail_if_old_scipy (array_type , ndim ))
213227 arr = array_type (np_arr )
214228
215229 result = stats .mean (arr , axis = axis ) # type: ignore[arg-type] # https://github.com/python/mypy/issues/16777
@@ -224,10 +238,13 @@ def test_mean(array_type: ArrayType[Array], axis: Literal[0, 1] | None, np_arr:
224238
225239@pytest .mark .array_type (skip = Flags .Disk )
226240def test_mean_var (
241+ request : pytest .FixtureRequest ,
227242 array_type : ArrayType [CpuArray | GpuArray | types .DaskArray ],
228243 axis : Literal [0 , 1 ] | None ,
229244 np_arr : NDArray [DTypeIn ],
245+ ndim : Literal [1 , 2 ],
230246) -> None :
247+ request .applymarker (_xfail_if_old_scipy (array_type , ndim ))
231248 arr = array_type (np_arr )
232249
233250 mean , var = stats .mean_var (arr , axis = axis , correction = 1 )
0 commit comments