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

CI: Add a check that Python.h is included first in any file using Python features. #5

Open
wants to merge 142 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
33b3825
Add new functions to config.h
steppi Feb 7, 2024
196b6e1
MAINT: Translate Cephes hyp2f1 to C++
steppi Feb 15, 2024
bc92dea
EMPTY: [skip actions] [skip cirrus]
steppi Jan 28, 2024
0cf9ec0
EMPTY: [skip actions] [skip cirrus]
steppi Jan 28, 2024
a148863
EMPTY: [skip actions] [skip cirrus]
steppi Jan 28, 2024
8c9bf25
Use C++ implementations for cephes functions
steppi Feb 21, 2024
e5d4a36
Translate besselpoly to C++
steppi Feb 21, 2024
f4fcab5
Translate i0, i1, i0e, i1e to C++ from cephes
steppi Feb 21, 2024
73e5dec
Add note about besselpoly translation
steppi Feb 21, 2024
48d235a
Add missing declarations of functions as inline
steppi Feb 21, 2024
0fd5165
Translate cephes iv to C++
steppi Feb 21, 2024
fd424df
Add missing #pragma once to scipy_iv.h
steppi Feb 21, 2024
7a74d2f
Translate cephes j0, j1 to C++
steppi Feb 21, 2024
7a1bf8e
Check in changes so I can switch branch
steppi Feb 21, 2024
519d083
Translate cephes jv to C++
steppi Feb 21, 2024
d797b29
Add C wrappers for C++ special functions
steppi Feb 22, 2024
58c2284
Check in missing cephes headers
steppi Feb 22, 2024
c437173
Translate cephes k0 to C++
steppi Feb 22, 2024
8b00e00
Make k0 inline
steppi Feb 22, 2024
178d8db
Remove unnecessary include
steppi Feb 22, 2024
d382c9b
Clang format code
steppi Feb 22, 2024
7b2e7a2
Translate cephes k1 to C++
steppi Feb 22, 2024
117ad11
Translate cephes kn to C++
steppi Feb 22, 2024
af8bea7
Translate more things from cephes
steppi Feb 22, 2024
266f161
Translate still more of cephes into C++
steppi Feb 22, 2024
00a1cef
Use cephes C++ impl in cbrt ufunc
steppi Feb 22, 2024
4738c81
Translate cephes hyperg (hyp1f1) to C++
steppi Feb 23, 2024
122e25b
Translate cephes expn to C++
steppi Mar 28, 2024
ad8c6e1
Add fmod to config.h
steppi Mar 28, 2024
cedbc0e
Translate cephes elliptic integrals to C++
steppi Mar 29, 2024
f7da18e
Translate more cephes trig functions
steppi Mar 29, 2024
6f7c059
Translate more cephes stuff
steppi Mar 29, 2024
2e0ac59
Clang format code
steppi Mar 29, 2024
f55512f
Translate more cephes stuff
steppi Mar 29, 2024
226e550
Translate more cephes stuff
steppi Mar 29, 2024
174f6e1
Translate F distribution functions to C++
steppi Mar 29, 2024
3b2c9bf
squash with previous
steppi Mar 29, 2024
6c1c8c2
Translate cephes gamma distribution stuff to C++
steppi Mar 29, 2024
50229f8
Translate cephes negative binomial functions to C++
steppi Mar 29, 2024
e68bc05
Translate cephes Poisson distribution functions to C++
steppi Mar 29, 2024
4027e41
Remove extra blank line
steppi Mar 29, 2024
1030de8
Add clamp and fix merge conflicts
steppi Mar 30, 2024
2d80514
Add more functions
steppi Apr 2, 2024
ed5a61d
Translate cephes frensl to C++
steppi Apr 2, 2024
b776437
Apply clang format
steppi Apr 2, 2024
26abb6c
Translate cephes owens_t to C++
steppi Apr 2, 2024
758deae
Add missing pragma once's
steppi Apr 2, 2024
24c203d
Translate cephes tukeylambdacdf to C++
steppi Apr 2, 2024
2f8957f
Translate cephes round to C++
steppi Apr 2, 2024
59707ff
Add missing #pragma once
steppi Apr 2, 2024
8d430ac
Translate cephes spence to C++
steppi Apr 2, 2024
8232d18
Translate cephes sici to C++
steppi Apr 2, 2024
574de2b
Translate cephes shichi to C++
steppi Apr 2, 2024
cca87a8
Swap to C++ sici in functions.json
steppi Apr 2, 2024
3ea906b
Check in, in-progress float128 header
steppi Apr 4, 2024
caf4628
Minor updates to float128.h
steppi Apr 4, 2024
755e653
cephes translation is nearing completion
steppi Apr 4, 2024
db741d4
Get error handling working in C wrappers of C++ funcs
steppi Apr 4, 2024
0210d2c
Fix path to include
steppi Apr 4, 2024
589d07c
Start using C++ cephes in Cython functions dependent on cephes
steppi Apr 5, 2024
833b879
Use C++ cephes polevl in Cython files
steppi Apr 5, 2024
27fd376
Overload type conversion operators for DoubleDouble
steppi Apr 5, 2024
d8003c1
Implement != operators for DoubleDouble
steppi Apr 5, 2024
880b458
Add infinity and quiet_NaN for DoubleDouble type
steppi Apr 5, 2024
ad4cbb8
Remove unnecessary DoubleDouble functions
steppi Apr 5, 2024
b4c0346
Add exp and log for C++ double double
steppi Apr 5, 2024
571c33b
Clang format code
steppi Apr 5, 2024
841399e
Translate kolmogorov and smirnov functions to C++
steppi Apr 6, 2024
2a9bd8c
Fix smirnov bug
steppi Apr 6, 2024
f4ee49f
Unhook old cephes in more places
steppi Apr 6, 2024
a1d1cea
npy_math include must come first
steppi Apr 6, 2024
d2b75d3
Start using c wrappers for double double arithmetic
steppi Apr 6, 2024
c872b7d
Remove C cephes and finishing touches that allow this
steppi Apr 6, 2024
3132463
EMPTY: [skip ci]
steppi Apr 6, 2024
14d6657
Remove now unneeded cephes headers
steppi Apr 6, 2024
99cf93b
Fix bug in double double exp
steppi Apr 6, 2024
aeb6f6e
Fix bug in _kolmogi, nan when should be inf
steppi Apr 6, 2024
1124858
Terminate when nonfinite value reached in cephes yn
steppi Apr 6, 2024
fa45204
Adjust position of unary - in C++ cephes lbeta to match original
steppi Apr 6, 2024
41c1fec
Add header with original copyright to translation of double-double
steppi Apr 6, 2024
e3e0d9d
Clang format code
steppi Apr 6, 2024
dc0d69a
Add helpful comments
steppi Apr 6, 2024
5f19611
Fix amos bug, missing return block
steppi Apr 7, 2024
8658be8
Remove cephes-lib from special_ufuncs
steppi Apr 7, 2024
4046372
EMPTY: [skip ci]
steppi Apr 7, 2024
6ef3d55
Fix conflicts with #20403
steppi Apr 7, 2024
f320d62
Apply suggestions from code review
steppi Apr 8, 2024
168d840
Remove unneeded include
steppi Apr 8, 2024
abd03ee
Get rid of dd_real namespace
steppi Apr 8, 2024
61b4869
Get rid of unnecessary ThreeProbs constructor
steppi Apr 8, 2024
2e560af
Disable compiler optimizations for lgam_sgn on 32bit gcc
steppi Apr 10, 2024
743a2a3
Only disable optimizations for lgam large_x calculation
steppi Apr 10, 2024
9039852
Clang format code.
steppi Apr 10, 2024
820ed56
Finish resolving merge conflicts
steppi Apr 10, 2024
5223836
Merged
Apr 15, 2024
3f7d5b7
Added missing pragma once
Apr 15, 2024
4f39582
merged
Apr 19, 2024
a0c420e
fixes for rebasing;
Apr 19, 2024
433dbdc
Removed _special.h
Apr 19, 2024
e8be98e
BUG: fix spherical_in for n=1 and z=0 (#20527)
PicoCentauri Apr 19, 2024
b4be3c9
TST: Adapt to `__array__(copy=True)`
thalassemia Apr 19, 2024
546e1e5
ENH: stats.moment: add array API support (#20292)
mdhaber Apr 19, 2024
b4f3037
Merge pull request #20533 from thalassemia/array_copy
tylerjereddy Apr 19, 2024
d5890e2
Remove unnecessary static's from variables
steppi Apr 19, 2024
d406754
TST: _lib: remove redundant test for missing `stacklevel` (#20538)
j-bowhay Apr 20, 2024
788b54a
MAINT: stats.skew: remove dead code
mdhaber Apr 20, 2024
bb35756
MAINT: stats.skew: simplify NumPy code
mdhaber Apr 20, 2024
0d33968
ENH: stats.skew: convert to array API
mdhaber Apr 20, 2024
f305bdf
Merge pull request #20390 from steppi/all-of-cephes-cpp
rgommers Apr 20, 2024
69d0c8a
TST: stats.skew: make tests array-api compatible
mdhaber Apr 20, 2024
0b7317d
MAINT: stats: raise when keepdims/nan_policy used with non-np backend
mdhaber Apr 20, 2024
7d4600e
Merge pull request #20541 from mdhaber/xp_skew
tupui Apr 20, 2024
fd014c4
BLD: Accelerate builds should not define `NO_APPEND_FORTRAN`
thalassemia Apr 20, 2024
882a922
BUG:linalg:bandwidth: Fix upper band stopping criterion (#20534)
tuhinsharma121 Apr 21, 2024
465805a
Merge pull request #20542 from thalassemia/acc_fortran_append
rgommers Apr 21, 2024
81c370e
DEV: Add script to check that Python.h is included first
DWesl Apr 17, 2024
54c72c0
CI: Add CI job to check if Python.h is included first.
DWesl Apr 17, 2024
c2ac82f
BLD: Move python-including headers earlier in their files.
DWesl Apr 17, 2024
62c46ec
DEV: Extend the list of python-including headers as we go
DWesl Apr 17, 2024
4f20123
DEV: Add npy_ namespace to list of python-implying constructs
DWesl Apr 17, 2024
64885a9
DEV: Tell script ni_support.h includes python
DWesl Apr 17, 2024
a250d3c
DEV: Only warn once for python-implying constructs in a file
DWesl Apr 18, 2024
9f276df
DEV: Don't warn for python constructs in headers
DWesl Apr 18, 2024
c9d78ee
DEV: Add very basic comment-parsing to python.h checker
DWesl Apr 18, 2024
390fa51
CI: Check files for duplicate header includes.
DWesl Apr 19, 2024
809f17a
Revert "CI: Check files for duplicate header includes."
DWesl Apr 19, 2024
735b62b
STY: Fix style issues of tools/check_python_h_first.py.
DWesl Apr 20, 2024
00cea9a
CI: Exclude HighsPy from checks.
DWesl Apr 19, 2024
d9f8b97
STY: Fix linter errors
DWesl Apr 20, 2024
26d35a4
CI: Move Python.h checker into Lint job.
DWesl Apr 20, 2024
f832659
PERF: Use regex method instead of module function
DWesl Apr 20, 2024
320620e
DEV: Add python.h checker to lint.py
DWesl Apr 21, 2024
bf99c0c
DEV: Move check_python_h_first linter from lint.py to dev.py
DWesl Apr 22, 2024
b588b49
DEV: Add --diff-against command-line flag like lint.py.
DWesl Apr 22, 2024
5727f21
STY:BUG: Move more python-including files earlier.
DWesl Apr 22, 2024
dc6ee07
STY: Wrap lines in dev.py and add .[ch]xx files to CI
DWesl Apr 22, 2024
88415ea
STY:FIX: Remove extra blank line added to lint.py
DWesl Apr 22, 2024
e53d93c
Update tools/lint.py
rgommers Apr 23, 2024
fa15201
DEV: fix running plain `python tools/check_python_h_first.py`
rgommers Apr 23, 2024
fd649c9
MAINT: undo now unnecessary change to tools/lint.py
rgommers Apr 23, 2024
dc0e1ef
MAINT: combine linter tasks in dev.py
rgommers Apr 23, 2024
725dfb8
Update .github/workflows/lint.yml
rgommers Apr 23, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/array_api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,5 @@ jobs:
python dev.py --no-build test -b all -s fft -- --durations 3 --timeout=60
python dev.py --no-build test -b all -t scipy.special.tests.test_support_alternative_backends -- --durations 3 --timeout=60
python dev.py --no-build test -b all -t scipy._lib.tests.test_array_api
python dev.py --no-build test -b all -t scipy._lib.tests.test__util -- --durations 3 --timeout=60
python dev.py --no-build test -b all -t scipy.stats.tests.test_stats -- --durations 3 --timeout=60
5 changes: 5 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ jobs:
python tools/lint.py --diff-against origin/$GITHUB_BASE_REF
python tools/unicode-check.py
python tools/check_test_name.py

- name: Check that Python.h is first in any file including it.
shell: bash
run: |
python tools/check_python_h_first.py
18 changes: 18 additions & 0 deletions dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,23 @@ def task_lint(fix):
'doc': 'Lint only files modified since last commit (stricter rules)',
}

@task_params([])
def task_check_python_h_first():
# Lint just the diff since branching off of main using a
# stricter configuration.
# emit_cmdstr(os.path.join('tools', 'lint.py') + ' --diff-against main')
cmd = "{!s} --diff-against=main".format(
Dirs().root / 'tools' / 'check_python_h_first.py'
)
return {
'basename': 'check_python_h_first',
'actions': [cmd],
'doc': (
'Check Python.h order only files modified since last commit '
'(stricter rules)'
),
}


def task_unicode_check():
# emit_cmdstr(os.path.join('tools', 'unicode-check.py'))
Expand Down Expand Up @@ -955,6 +972,7 @@ def run(cls, fix):
'lint': {'fix': fix},
'unicode-check': {},
'check-testname': {},
'check_python_h_first': {},
})


Expand Down
30 changes: 26 additions & 4 deletions doc/source/dev/api-dev/array_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,13 @@ variable is set:
Support is provided in `scipy.special` for the following functions:
`scipy.special.log_ndtr`, `scipy.special.ndtr`, `scipy.special.ndtri`,
`scipy.special.erf`, `scipy.special.erfc`, `scipy.special.i0`,
`scipy.special.i0e`, `scipy.special.i1`, `scipy.special.i1e`,
`scipy.special.i0e`, `scipy.special.i1`, `scipy.special.i1e`,
`scipy.special.gammaln`, `scipy.special.gammainc`, `scipy.special.gammaincc`,
`scipy.special.logit`, and `scipy.special.expit`.

Support is provided in `scipy.stats` for the following functions:
`scipy.stats.pearsonr` and `scipy.stats.moment`.


Implementation notes
--------------------
Expand Down Expand Up @@ -164,7 +167,7 @@ have to change is:

Input array validation uses the following pattern::

xp = array_namespace(arr) # where arr is the input array
xp = array_namespace(arr) # where arr is the input array
# alternatively, if there are multiple array inputs, include them all:
xp = array_namespace(arr1, arr2)

Expand Down Expand Up @@ -235,10 +238,22 @@ The following pytest markers are available:
other than the default NumPy backend.
``@pytest.mark.usefixtures("skip_xp_backends")`` must be used alongside this
marker for the skipping to apply.
* ``skip_xp_invalid_arg`` is used to skip tests that use arguments which
are invalid when ``SCIPY_ARRAY_API`` is used. For instance, some tests of
`scipy.stats` functions pass masked arrays to the function being tested, but
masked arrays are incompatible with the array API. Use of the
``skip_xp_invalid_arg`` decorator allows these tests to protect against
regressions when ``SCIPY_ARRAY_API`` is not used without resulting in failures
when ``SCIPY_ARRAY_API`` is used. In time, we will want these functions to emit
deprecation warnings when they receive array API invalid input, and this
decorator will check that the deprecation warning is emitted without it
causing the test to fail. When ``SCIPY_ARRAY_API=1`` behavior becomes the
default and only behavior, these tests (and the decorator itself) will be
removed.

The following is an example using the markers::

from scipy.conftest import array_api_compatible
from scipy.conftest import array_api_compatible, skip_xp_invalid_arg
...
@pytest.mark.skip_xp_backends(np_only=True,
reasons=['skip reason'])
Expand All @@ -258,6 +273,13 @@ The following is an example using the markers::
a = xp.asarray([1, 2, 3])
b = xp.asarray([0, 2, 5])
toto(a, b)
...
# Do not run when SCIPY_ARRAY_API is used
@skip_xp_invalid_arg
def test_toto_masked_array(self):
a = np.ma.asarray([1, 2, 3])
b = np.ma.asarray([0, 2, 5])
toto(a, b)

Passing a custom reason to ``reasons`` when ``cpu_only=True`` is unsupported
since ``cpu_only=True`` can be used alongside passing ``backends``. Also,
Expand All @@ -269,7 +291,7 @@ compatibility, one can reduce verbosity by telling ``pytest`` to apply the
markers to every test function using ``pytestmark``::

from scipy.conftest import array_api_compatible

pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends")]
skip_xp_backends = pytest.mark.skip_xp_backends
...
Expand Down
5 changes: 3 additions & 2 deletions scipy/_build_utils/_wrappers_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
USE_OLD_ACCELERATE = ['lsame', 'dcabs1']

C_PREAMBLE = """
#include "fortran_defs.h"
#include "npy_cblas.h"
#include "fortran_defs.h"
"""

LAPACK_DECLS = """
Expand Down Expand Up @@ -128,7 +128,8 @@ def get_blas_macro_and_name(name, accelerate):
elif name == 'xerbla_array':
return '', name + '__'
if name in WRAPPED_FUNCS:
return '', name + 'wrp_'
name = name + 'wrp'
return 'F_FUNC', f'{name},{name.upper()}'
return 'BLAS_FUNC', name


Expand Down
12 changes: 7 additions & 5 deletions scipy/_build_utils/src/npy_cblas.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ enum CBLAS_SIDE {CblasLeft=141, CblasRight=142};

#define CBLAS_INDEX size_t /* this may vary between platforms */

#ifdef ACCELERATE_NEW_LAPACK
#define NO_APPEND_FORTRAN
#define BLAS_SYMBOL_SUFFIX $NEWLAPACK
#endif

#ifdef NO_APPEND_FORTRAN
#define BLAS_FORTRAN_SUFFIX
#else
#define BLAS_FORTRAN_SUFFIX _
#endif

// New Accelerate suffix is always $NEWLAPACK (no underscore)
#ifdef ACCELERATE_NEW_LAPACK
#undef BLAS_FORTRAN_SUFFIX
#define BLAS_FORTRAN_SUFFIX
#define BLAS_SYMBOL_SUFFIX $NEWLAPACK
#endif

#ifndef BLAS_SYMBOL_PREFIX
#define BLAS_SYMBOL_PREFIX
#endif
Expand Down
2 changes: 1 addition & 1 deletion scipy/_build_utils/src/wrap_dummy_g77_abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ passing a pointer to a variable in which to store the computed result. Unlike
return values, struct complex arguments work without segfaulting.
*/

#include "fortran_defs.h"
#include "npy_cblas.h"
#include "fortran_defs.h"

#ifdef __cplusplus
extern "C" {
Expand Down
2 changes: 1 addition & 1 deletion scipy/_build_utils/src/wrap_g77_abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ passing a pointer to a variable in which to store the computed result. Unlike
return values, struct complex arguments work without segfaulting.
*/

#include "fortran_defs.h"
#include "npy_cblas.h"
#include "fortran_defs.h"

#ifdef __cplusplus
extern "C" {
Expand Down
26 changes: 18 additions & 8 deletions scipy/_lib/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
)

import numpy as np
from scipy._lib._array_api import array_namespace
from scipy._lib._array_api import array_namespace, is_numpy


AxisError: type[Exception]
Expand Down Expand Up @@ -708,23 +708,29 @@ def _nan_allsame(a, axis, keepdims=False):


def _contains_nan(a, nan_policy='propagate', use_summation=True,
policies=None):
if not isinstance(a, np.ndarray):
policies=None, *, xp=None):
if xp is None:
xp = array_namespace(a)
not_numpy = not is_numpy(xp)

if not_numpy:
use_summation = False # some array_likes ignore nans (e.g. pandas)
if policies is None:
policies = ['propagate', 'raise', 'omit']
if nan_policy not in policies:
raise ValueError("nan_policy must be one of {%s}" %
', '.join("'%s'" % s for s in policies))

if np.issubdtype(a.dtype, np.inexact):
# The summation method avoids creating a (potentially huge) array.
inexact = (xp.isdtype(a.dtype, "real floating")
or xp.isdtype(a.dtype, "complex floating"))
if inexact:
# The summation method avoids creating another (potentially huge) array
if use_summation:
with np.errstate(invalid='ignore', over='ignore'):
contains_nan = np.isnan(np.sum(a))
contains_nan = xp.isnan(xp.sum(a))
else:
contains_nan = np.isnan(a).any()
elif np.issubdtype(a.dtype, object):
contains_nan = xp.any(xp.isnan(a))
elif is_numpy(xp) and np.issubdtype(a.dtype, object):
contains_nan = False
for el in a.ravel():
# isnan doesn't work on non-numeric elements
Expand All @@ -738,6 +744,10 @@ def _contains_nan(a, nan_policy='propagate', use_summation=True,
if contains_nan and nan_policy == 'raise':
raise ValueError("The input contains nan values")

if not_numpy and contains_nan and nan_policy=='omit':
message = "`nan_policy='omit' is incompatible with non-NumPy arrays."
raise ValueError(message)

return contains_nan, nan_policy


Expand Down
45 changes: 37 additions & 8 deletions scipy/_lib/tests/test__util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
from pytest import raises as assert_raises
import hypothesis.extra.numpy as npst
from hypothesis import given, strategies, reproduce_failure # noqa: F401
from scipy.conftest import array_api_compatible
from scipy.conftest import array_api_compatible, skip_xp_invalid_arg

from scipy._lib._array_api import xp_assert_equal, xp_assert_close
from scipy._lib._array_api import (xp_assert_equal, xp_assert_close, is_numpy,
copy as xp_copy)
from scipy._lib._util import (_aligned_zeros, check_random_state, MapWrapper,
getfullargspec_no_self, FullArgSpec,
rng_integers, _validate_int, _rename_parameter,
Expand Down Expand Up @@ -302,7 +303,7 @@ def test_policy(self):
with pytest.raises(ValueError, match=msg):
_contains_nan(data, nan_policy="nan")

def test_contains_nan_1d(self):
def test_contains_nan(self):
data1 = np.array([1, 2, 3])
assert not _contains_nan(data1)[0]

Expand All @@ -312,17 +313,18 @@ def test_contains_nan_1d(self):
data3 = np.array([np.nan, 2, 3, np.nan])
assert _contains_nan(data3)[0]

data4 = np.array([1, 2, "3", np.nan]) # converted to string "nan"
data4 = np.array([[1, 2], [3, 4]])
assert not _contains_nan(data4)[0]

data5 = np.array([1, 2, "3", np.nan], dtype='object')
data5 = np.array([[1, 2], [3, np.nan]])
assert _contains_nan(data5)[0]

def test_contains_nan_2d(self):
data1 = np.array([[1, 2], [3, 4]])
@skip_xp_invalid_arg
def test_contains_nan_with_strings(self):
data1 = np.array([1, 2, "3", np.nan]) # converted to string "nan"
assert not _contains_nan(data1)[0]

data2 = np.array([[1, 2], [3, np.nan]])
data2 = np.array([1, 2, "3", np.nan], dtype='object')
assert _contains_nan(data2)[0]

data3 = np.array([["1", 2], [3, np.nan]]) # converted to string "nan"
Expand All @@ -331,6 +333,33 @@ def test_contains_nan_2d(self):
data4 = np.array([["1", 2], [3, np.nan]], dtype='object')
assert _contains_nan(data4)[0]

@array_api_compatible
@pytest.mark.parametrize("nan_policy", ['propagate', 'omit', 'raise'])
def test_array_api(self, xp, nan_policy):
rng = np.random.default_rng(932347235892482)
x0 = rng.random(size=(2, 3, 4))
x = xp.asarray(x0)
x_nan = xp_copy(x, xp=xp)
x_nan[1, 2, 1] = np.nan

contains_nan, nan_policy_out = _contains_nan(x, nan_policy=nan_policy)
assert not contains_nan
assert nan_policy_out == nan_policy

if nan_policy == 'raise':
message = 'The input contains...'
with pytest.raises(ValueError, match=message):
_contains_nan(x_nan, nan_policy=nan_policy)
elif nan_policy == 'omit' and not is_numpy(xp):
message = "`nan_policy='omit' is incompatible..."
with pytest.raises(ValueError, match=message):
_contains_nan(x_nan, nan_policy=nan_policy)
elif nan_policy == 'propagate':
contains_nan, nan_policy_out = _contains_nan(
x_nan, nan_policy=nan_policy)
assert contains_nan
assert nan_policy_out == nan_policy


def test__rng_html_rewrite():
def mock_str():
Expand Down
20 changes: 0 additions & 20 deletions scipy/_lib/tests/test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,23 +115,3 @@ def test_warning_calls_filters(warning_calls):
"found in:\n {}".format(
"\n ".join(bad_filters)))


@pytest.mark.slow
@pytest.mark.xfail(reason="stacklevels currently missing")
def test_warning_calls_stacklevels(warning_calls):
bad_filters, bad_stacklevels = warning_calls

msg = ""

if bad_filters:
msg += ("warning ignore filter should not be used, instead, use\n"
"numpy.testing.suppress_warnings (in tests only);\n"
"found in:\n {}".format("\n ".join(bad_filters)))
msg += "\n\n"

if bad_stacklevels:
msg += "warnings should have an appropriate stacklevel:\n {}".format(
"\n ".join(bad_stacklevels))

if msg:
raise AssertionError(msg)
4 changes: 4 additions & 0 deletions scipy/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ def check_fpu_mode(request):

array_api_compatible = pytest.mark.parametrize("xp", xp_available_backends.values())

skip_xp_invalid_arg = pytest.mark.skipif(SCIPY_ARRAY_API,
reason = ('Test involves masked arrays, object arrays, or other types '
'that are not valid input when `SCIPY_ARRAY_API` is used.'))


@pytest.fixture
def skip_xp_backends(xp, request):
Expand Down
5 changes: 2 additions & 3 deletions scipy/io/_fast_matrix_market/src/_fmm_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// Use of this source code is governed by the BSD 2-clause license found in the LICENSE.txt file.
// SPDX-License-Identifier: BSD-2-Clause

#include <Python.h>
#include "_fmm_core.hpp"

#include <fast_matrix_market/types.hpp>
#include <cstdint>
namespace fast_matrix_market {
Expand All @@ -17,8 +18,6 @@ namespace fast_matrix_market {
}
#include <fast_matrix_market/fast_matrix_market.hpp>

#include "_fmm_core.hpp"

////////////////////////////////////////////////
//// Header methods
////////////////////////////////////////////////
Expand Down
6 changes: 4 additions & 2 deletions scipy/linalg/_cythonized_array_utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ cdef inline (int, int) band_check_internal_c(const np_numeric_t[:, ::1]A) noexce
if A[r, c] != zero:
upper_band = c - r
break
if upper_band == c:
# If existing band falls outside matrix; we are done
if r + 1 + upper_band > m - 1:
break

return lower_band, upper_band
Expand Down Expand Up @@ -229,7 +230,8 @@ cdef inline (int, int) band_check_internal_noncontig(const np_numeric_t[:, :]A)
if A[r, c] != zero:
upper_band = c - r
break
if upper_band == c:
# If existing band falls outside matrix; we are done
if r + 1 + upper_band > m - 1:
break

return lower_band, upper_band
Expand Down
Loading