Skip to content

Commit 8c56923

Browse files
Update tests for non-0D scalar conversion rules (#2694)
This PR updates dpnp tests for non-0D scalar conversion behavior changes in [dpctl-2223](IntelPython/dpctl#2223) - allowing scalar conversion only for 0D `usm_ndarray`
1 parent 928f20e commit 8c56923

File tree

5 files changed

+84
-44
lines changed

5 files changed

+84
-44
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Also, that release drops support for Python 3.9, making Python 3.10 the minimum
4040
* Unified public API definitions in `dpnp.linalg` and `dpnp.scipy` submodules [#2663](https://github.com/IntelPython/dpnp/pull/2663)
4141
* Aligned the signature of `dpnp.reshape` function with Python array API by making `shape` a required argument [#2673](https://github.com/IntelPython/dpnp/pull/2673)
4242
* Unified `dpnp` public API exports by consolidating function exports in `__init__.py` and removing wildcard imports [#2665](https://github.com/IntelPython/dpnp/pull/2665) [#2666](https://github.com/IntelPython/dpnp/pull/2666)
43+
* Updated tests to reflect the new scalar conversion rules for non-0D `usm_ndarray` [#2694](https://github.com/IntelPython/dpnp/pull/2694)
4344

4445
### Deprecated
4546

dpnp/tests/test_indexing.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -766,12 +766,18 @@ def test_axis_as_array(self):
766766
a = numpy.array([[[1]]])
767767
ia = dpnp.array(a)
768768

769-
result = ia.take([0], axis=ia)
770-
expected = a.take(
771-
[0], axis=1
772-
) # numpy raises an error for axis as array
769+
# axis is a 0-D integer array
770+
axis_0d = numpy.array(1)
771+
iaxis_0d = dpnp.array(1)
772+
773+
result = ia.take([0], axis=iaxis_0d)
774+
expected = a.take([0], axis=axis_0d)
773775
assert_array_equal(result, expected)
774776

777+
# axis is not a 0-D integer array
778+
assert_raises(TypeError, ia.take, [0], axis=ia)
779+
assert_raises(TypeError, a.take, [0], axis=a)
780+
775781
def test_mode_raise(self):
776782
a = dpnp.array([[1, 2], [3, 4]])
777783
assert_raises(ValueError, a.take, [-1, 4], mode="raise")

dpnp/tests/test_ndarray.py

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
assert_allclose,
66
assert_array_equal,
77
assert_equal,
8+
assert_raises,
89
assert_raises_regex,
910
)
1011

@@ -530,43 +531,71 @@ def test_print_dpnp_zero_shape():
530531
assert result == expected
531532

532533

533-
# Numpy will raise an error when converting a.ndim > 0 to a scalar
534-
# TODO: Discuss dpnp behavior according to these future changes
535-
@pytest.mark.skip("until dpctl-2223")
536-
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
537-
@pytest.mark.parametrize("func", [bool, float, int, complex])
534+
@testing.with_requires("numpy>=2.4")
535+
@pytest.mark.parametrize("xp", [dpnp, numpy])
538536
@pytest.mark.parametrize("shape", [tuple(), (1,), (1, 1), (1, 1, 1)])
539-
@pytest.mark.parametrize(
540-
"dtype", get_all_dtypes(no_float16=False, no_complex=True)
541-
)
542-
def test_scalar_type_casting(func, shape, dtype):
543-
a = numpy.full(shape, 5, dtype=dtype)
544-
ia = dpnp.full(shape, 5, dtype=dtype)
545-
assert func(a) == func(ia)
546-
537+
class TestPythonScalarConversion:
538+
@pytest.mark.parametrize(
539+
"dtype", get_all_dtypes(no_none=True, no_float16=False, no_complex=True)
540+
)
541+
def test_bool_conversion(self, xp, shape, dtype):
542+
a = xp.full(shape, 5, dtype=dtype)
543+
if xp == dpnp and len(shape) > 0:
544+
# dpnp behavior differs from NumPy:
545+
# non-0D singe-element arrays are not convertible to
546+
# Python bool
547+
assert_raises(TypeError, bool, a)
548+
else:
549+
# NumPy allows conversion to Python bool for
550+
# non-0D singe-element arrays
551+
assert bool(a) is True
547552

548-
# Numpy will raise an error when converting a.ndim > 0 to a scalar
549-
# TODO: Discuss dpnp behavior according to these future changes
550-
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
551-
@pytest.mark.skip("until dpctl-2223")
552-
@pytest.mark.parametrize(
553-
"method", ["__bool__", "__float__", "__int__", "__complex__"]
554-
)
555-
@pytest.mark.parametrize("shape", [tuple(), (1,), (1, 1), (1, 1, 1)])
556-
@pytest.mark.parametrize(
557-
"dtype", get_all_dtypes(no_float16=False, no_complex=True)
558-
)
559-
def test_scalar_type_casting_by_method(method, shape, dtype):
560-
a = numpy.full(shape, 4.7, dtype=dtype)
561-
ia = dpnp.full(shape, 4.7, dtype=dtype)
562-
assert_allclose(getattr(a, method)(), getattr(ia, method)(), rtol=1e-06)
553+
@pytest.mark.parametrize(
554+
"dtype", get_all_dtypes(no_none=True, no_float16=False, no_complex=True)
555+
)
556+
def test_bool_method_conversion(self, xp, shape, dtype):
557+
a = xp.full(shape, 5, dtype=dtype)
558+
if xp == dpnp and len(shape) > 0:
559+
assert_raises(TypeError, getattr(a, "__bool__"))
560+
else:
561+
assert a.__bool__() is True
562+
563+
@pytest.mark.parametrize("func", [float, int, complex])
564+
@pytest.mark.parametrize(
565+
"dtype", get_all_dtypes(no_none=True, no_float16=False, no_complex=True)
566+
)
567+
def test_non_bool_conversion(self, xp, func, shape, dtype):
568+
a = xp.full(shape, 5, dtype=dtype)
569+
if len(shape) > 0:
570+
# Non-0D arrays are not allowed to be converted to
571+
# Python numeric scalars
572+
assert_raises(TypeError, func, a)
573+
else:
574+
# 0D arrays are allowed to be converted to
575+
# Python numeric scalars
576+
expected = 1 if dtype == xp.bool else 5
577+
assert func(a) == func(expected)
578+
579+
@pytest.mark.parametrize("method", ["__float__", "__int__", "__complex__"])
580+
@pytest.mark.parametrize(
581+
"dtype", get_all_dtypes(no_none=True, no_float16=False, no_complex=True)
582+
)
583+
def test_non_bool_method_conversion(self, xp, method, shape, dtype):
584+
a = xp.full(shape, 5, dtype=dtype)
585+
if len(shape) > 0:
586+
assert_raises(TypeError, getattr(a, method))
587+
else:
588+
expected = 1 if dtype == xp.bool else 5
589+
func = {"__float__": float, "__int__": int, "__complex__": complex}[
590+
method
591+
]
592+
assert getattr(a, method)() == func(expected)
563593

564594

565-
@pytest.mark.parametrize("shape", [(1,), (1, 1), (1, 1, 1)])
566595
@pytest.mark.parametrize("index_dtype", [dpnp.int32, dpnp.int64])
567-
def test_array_as_index(shape, index_dtype):
568-
ind_arr = dpnp.ones(shape, dtype=index_dtype)
569-
a = numpy.arange(ind_arr.size + 1)
596+
def test_array_as_index(index_dtype):
597+
ind_arr = dpnp.ones((1,), dtype=index_dtype)
598+
a = dpnp.arange(ind_arr.size + 1)
570599
assert a[tuple(ind_arr)] == a[1]
571600

572601

dpnp/tests/third_party/cupy/core_tests/test_ndarray_unary_op.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ def test_bool_scalar(self, dtype):
2525
assert not bool(cupy.array(0, dtype=dtype))
2626

2727
def test_bool_one_element_bool(self):
28-
assert bool(cupy.array([True], dtype=numpy.bool_))
29-
assert not bool(cupy.array([False], dtype=numpy.bool_))
28+
# Different behavior from CuPy:
29+
# CuPy as NumPy allows conversion to Python bool for
30+
# non-0D singe-element arrays
31+
with self.assertRaises(TypeError):
32+
bool(cupy.array([True], dtype=numpy.bool_))
3033

3134
@testing.for_all_dtypes()
3235
def test_bool_one_element(self, dtype):
33-
assert bool(cupy.array([1], dtype=dtype))
34-
assert not bool(cupy.array([0], dtype=dtype))
36+
# Different behavior from CuPy
37+
with self.assertRaises(TypeError):
38+
bool(cupy.array([1], dtype=dtype))
3539

3640
@testing.for_all_dtypes()
3741
def test_bool_two_elements(self, dtype):

dpnp/tests/third_party/cupyx/scipy_tests/special_tests/test_erf.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ def test_erfinv_behavior(self, dtype):
8080

8181
a[:] = 1.0 + 1e-6
8282
a = cupy.scipy.special.erfinv(a)
83-
assert cupy.isnan(a)
83+
assert cupy.isnan(a).item()
8484
a[:] = -1.0 - 1e-6
8585
a = cupy.scipy.special.erfinv(a)
86-
assert cupy.isnan(a)
86+
assert cupy.isnan(a).item()
8787
a[:] = 1.0
8888
a = cupy.scipy.special.erfinv(a)
8989
assert numpy.isposinf(cupy.asnumpy(a))
@@ -98,10 +98,10 @@ def test_erfcinv_behavior(self, dtype):
9898

9999
a[:] = 2.0 + 1e-6
100100
a = cupy.scipy.special.erfcinv(a)
101-
assert cupy.isnan(a)
101+
assert cupy.isnan(a).item()
102102
a[:] = 0.0 - 1e-6
103103
a = cupy.scipy.special.erfcinv(a)
104-
assert cupy.isnan(a)
104+
assert cupy.isnan(a).item()
105105
a[:] = 0.0
106106
a = cupy.scipy.special.erfcinv(a)
107107
assert numpy.isposinf(cupy.asnumpy(a))

0 commit comments

Comments
 (0)