Skip to content

Commit 03cdb80

Browse files
authored
TST: skip|xfail_xp_backends disregards reason= (scipy#22131)
* TST: skip|xfail_xp_backends suppresses reason= * reason from explicit backends should take precedence on np_only/cpu_only * docstring
1 parent fe518f1 commit 03cdb80

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

scipy/conftest.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,13 @@ def _backends_kwargs_from_request(request, skip_or_xfail):
229229
if marker.kwargs.get('np_only'):
230230
kwargs['np_only'] = True
231231
kwargs['exceptions'] = marker.kwargs.get('exceptions', [])
232+
kwargs['reason'] = marker.kwargs.get('reason', None)
232233
elif marker.kwargs.get('cpu_only'):
233234
if not kwargs.get('np_only'):
234235
# if np_only is given, it is certainly cpu only
235236
kwargs['cpu_only'] = True
236237
kwargs['exceptions'] = marker.kwargs.get('exceptions', [])
238+
kwargs['reason'] = marker.kwargs.get('reason', None)
237239

238240
# add backends, if any
239241
if len(marker.args) > 0:
@@ -291,22 +293,20 @@ def skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='skip'):
291293
Backends to skip/xfail, e.g. ``("array_api_strict", "torch")``.
292294
These are overriden when ``np_only`` is ``True``, and are not
293295
necessary to provide for non-CPU backends when ``cpu_only`` is ``True``.
294-
For a custom reason to apply, you should pass a dict ``{'reason': '...'}``
295-
to a keyword matching the name of the backend.
296-
reason : str, optional
297-
A reason for the skip/xfail in the case of ``np_only=True``.
298-
If unprovided, a default reason is used. Note that it is not possible
299-
to specify a custom reason with ``cpu_only``.
296+
For a custom reason to apply, you should pass
297+
``kwargs={<backend name>: {'reason': '...'}, ...}``.
300298
np_only : bool, optional
301299
When ``True``, the test is skipped/xfailed for all backends other
302300
than the default NumPy backend. There is no need to provide
303-
any ``backends`` in this case. To specify a reason, pass a
304-
value to ``reason``. Default: ``False``.
301+
any ``backends`` in this case. Default: ``False``.
305302
cpu_only : bool, optional
306303
When ``True``, the test is skipped/xfailed on non-CPU devices.
307304
There is no need to provide any ``backends`` in this case,
308305
but any ``backends`` will also be skipped on the CPU.
309306
Default: ``False``.
307+
reason : str, optional
308+
A reason for the skip/xfail in the case of ``np_only=True`` or
309+
``cpu_only=True``. If omitted, a default reason is used.
310310
exceptions : list, optional
311311
A list of exceptions for use with ``cpu_only`` or ``np_only``.
312312
This should be provided when delegation is implemented for some,
@@ -329,17 +329,32 @@ def skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='skip'):
329329
if exceptions and not (cpu_only or np_only):
330330
raise ValueError("`exceptions` is only valid alongside `cpu_only` or `np_only`")
331331

332+
# Test explicit backends first so that their reason can override
333+
# those from np_only/cpu_only
334+
if backends is not None:
335+
for i, backend in enumerate(backends):
336+
if xp.__name__ == backend:
337+
reason = kwargs[backend].get('reason')
338+
if not reason:
339+
reason = f"do not run with array API backend: {backend}"
340+
341+
skip_or_xfail(reason=reason)
342+
332343
if np_only:
333-
reason = kwargs.get("reason", "do not run with non-NumPy backends.")
334-
if not isinstance(reason, str) and len(reason) > 1:
335-
raise ValueError("please provide a singleton `reason` "
336-
"when using `np_only`")
344+
reason = kwargs.get("reason")
345+
if not reason:
346+
reason = "do not run with non-NumPy backends"
347+
337348
if xp.__name__ != 'numpy' and xp.__name__ not in exceptions:
338349
skip_or_xfail(reason=reason)
339350
return
351+
340352
if cpu_only:
341-
reason = ("no array-agnostic implementation or delegation available "
342-
"for this backend and device")
353+
reason = kwargs.get("reason")
354+
if not reason:
355+
reason = ("no array-agnostic implementation or delegation available "
356+
"for this backend and device")
357+
343358
exceptions = [] if exceptions is None else exceptions
344359
if SCIPY_ARRAY_API and SCIPY_DEVICE != 'cpu':
345360
if xp.__name__ == 'cupy' and 'cupy' not in exceptions:
@@ -352,15 +367,6 @@ def skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='skip'):
352367
if 'cpu' not in d.device_kind:
353368
skip_or_xfail(reason=reason)
354369

355-
if backends is not None:
356-
for i, backend in enumerate(backends):
357-
if xp.__name__ == backend:
358-
reason = kwargs[backend].get('reason')
359-
if not reason:
360-
reason = f"do not run with array API backend: {backend}"
361-
362-
skip_or_xfail(reason=reason)
363-
364370

365371
# Following the approach of NumPy's conftest.py...
366372
# Use a known and persistent tmpdir for hypothesis' caches, which

0 commit comments

Comments
 (0)