From 273ff4ebd5a798cb936028f90257ce576979cd6a Mon Sep 17 00:00:00 2001 From: crusaderky Date: Thu, 20 Feb 2025 13:03:23 +0000 Subject: [PATCH 1/2] rename test_utils -> test_helpers --- tests/{test_utils.py => test_helpers.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_utils.py => test_helpers.py} (100%) diff --git a/tests/test_utils.py b/tests/test_helpers.py similarity index 100% rename from tests/test_utils.py rename to tests/test_helpers.py From 7b90a4e4f2cbe7d5234773119980a739d0d05e93 Mon Sep 17 00:00:00 2001 From: crusaderky Date: Thu, 20 Feb 2025 13:05:27 +0000 Subject: [PATCH 2/2] refactor tests for asarrays --- tests/test_helpers.py | 181 +++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 92 deletions(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 699f25f1..f0d8224f 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -59,95 +59,92 @@ def test_xp(self, xp: ModuleType): xp_assert_equal(actual, expected) -@pytest.mark.xfail_xp_backend(Backend.SPARSE, reason="no isdtype") -@pytest.mark.parametrize( - ("dtype", "b", "defined"), - [ - # Well-defined cases of dtype promotion from Python scalar to Array - # bool vs. bool - ("bool", True, True), - # int vs. xp.*int*, xp.float*, xp.complex* - ("int16", 1, True), - ("uint8", 1, True), - ("float32", 1, True), - ("float64", 1, True), - ("complex64", 1, True), - ("complex128", 1, True), - # float vs. xp.float, xp.complex - ("float32", 1.0, True), - ("float64", 1.0, True), - ("complex64", 1.0, True), - ("complex128", 1.0, True), - # complex vs. xp.complex - ("complex64", 1.0j, True), - ("complex128", 1.0j, True), - # Undefined cases - ("bool", 1, False), - ("int64", 1.0, False), - ("float64", 1.0j, False), - ], -) -def test_asarrays_array_vs_scalar( - dtype: str, b: int | float | complex, defined: bool, xp: ModuleType -): - a = xp.asarray(1, dtype=getattr(xp, dtype)) - - xa, xb = asarrays(a, b, xp) - assert xa.dtype == a.dtype - if defined: - assert xb.dtype == a.dtype - else: - assert xb.dtype == xp.asarray(b).dtype - - xbr, xar = asarrays(b, a, xp) - assert xar.dtype == xa.dtype - assert xbr.dtype == xb.dtype - - -def test_asarrays_scalar_vs_scalar(xp: ModuleType): - a, b = asarrays(1, 2.2, xp=xp) - assert a.dtype == xp.asarray(1).dtype # Default dtype - assert b.dtype == xp.asarray(2.2).dtype # Default dtype; not broadcasted - - -ALL_TYPES = ( - "int8", - "int16", - "int32", - "int64", - "uint8", - "uint16", - "uint32", - "uint64", - "float32", - "float64", - "complex64", - "complex128", - "bool", -) - - -@pytest.mark.parametrize("a_type", ALL_TYPES) -@pytest.mark.parametrize("b_type", ALL_TYPES) -def test_asarrays_array_vs_array(a_type: str, b_type: str, xp: ModuleType): - """ - Test that when both inputs of asarray are already Array API objects, - they are returned unchanged. - """ - a = xp.asarray(1, dtype=getattr(xp, a_type)) - b = xp.asarray(1, dtype=getattr(xp, b_type)) - xa, xb = asarrays(a, b, xp) - assert xa.dtype == a.dtype - assert xb.dtype == b.dtype - - -@pytest.mark.parametrize("dtype", [np.float64, np.complex128]) -def test_asarrays_numpy_generics(dtype: type): - """ - Test special case of np.float64 and np.complex128, - which are subclasses of float and complex. - """ - a = dtype(0) - xa, xb = asarrays(a, 0, xp=np) - assert xa.dtype == dtype - assert xb.dtype == dtype +class TestAsArrays: + @pytest.mark.xfail_xp_backend(Backend.SPARSE, reason="no isdtype") + @pytest.mark.parametrize( + ("dtype", "b", "defined"), + [ + # Well-defined cases of dtype promotion from Python scalar to Array + # bool vs. bool + ("bool", True, True), + # int vs. xp.*int*, xp.float*, xp.complex* + ("int16", 1, True), + ("uint8", 1, True), + ("float32", 1, True), + ("float64", 1, True), + ("complex64", 1, True), + ("complex128", 1, True), + # float vs. xp.float, xp.complex + ("float32", 1.0, True), + ("float64", 1.0, True), + ("complex64", 1.0, True), + ("complex128", 1.0, True), + # complex vs. xp.complex + ("complex64", 1.0j, True), + ("complex128", 1.0j, True), + # Undefined cases + ("bool", 1, False), + ("int64", 1.0, False), + ("float64", 1.0j, False), + ], + ) + def test_array_vs_scalar( + self, dtype: str, b: int | float | complex, defined: bool, xp: ModuleType + ): + a = xp.asarray(1, dtype=getattr(xp, dtype)) + + xa, xb = asarrays(a, b, xp) + assert xa.dtype == a.dtype + if defined: + assert xb.dtype == a.dtype + else: + assert xb.dtype == xp.asarray(b).dtype + + xbr, xar = asarrays(b, a, xp) + assert xar.dtype == xa.dtype + assert xbr.dtype == xb.dtype + + def test_scalar_vs_scalar(self, xp: ModuleType): + a, b = asarrays(1, 2.2, xp=xp) + assert a.dtype == xp.asarray(1).dtype # Default dtype + assert b.dtype == xp.asarray(2.2).dtype # Default dtype; not broadcasted + + ALL_TYPES: tuple[str, ...] = ( + "int8", + "int16", + "int32", + "int64", + "uint8", + "uint16", + "uint32", + "uint64", + "float32", + "float64", + "complex64", + "complex128", + "bool", + ) + + @pytest.mark.parametrize("a_type", ALL_TYPES) + @pytest.mark.parametrize("b_type", ALL_TYPES) + def test_array_vs_array(self, a_type: str, b_type: str, xp: ModuleType): + """ + Test that when both inputs of asarray are already Array API objects, + they are returned unchanged. + """ + a = xp.asarray(1, dtype=getattr(xp, a_type)) + b = xp.asarray(1, dtype=getattr(xp, b_type)) + xa, xb = asarrays(a, b, xp) + assert xa.dtype == a.dtype + assert xb.dtype == b.dtype + + @pytest.mark.parametrize("dtype", [np.float64, np.complex128]) + def test_numpy_generics(self, dtype: type): + """ + Test special case of np.float64 and np.complex128, + which are subclasses of float and complex. + """ + a = dtype(0) + xa, xb = asarrays(a, 0, xp=np) + assert xa.dtype == dtype + assert xb.dtype == dtype