From bfa396148bd06b0040d5509c94eab9e002683f63 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Thu, 21 Apr 2022 16:55:58 +0100 Subject: [PATCH 1/8] Docstring for `ph.assert_dtype()` --- array_api_tests/pytest_helpers.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index 80e5b597..508e9de0 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -88,6 +88,31 @@ def assert_dtype( *, repr_name: str = "out.dtype", ): + """ + Tests the output dtype is as expected. + + We infer the expected dtype from in_dtype and to test out_dtype, e.g. + + >>> x = xp.arange(5, dtype=xp.uint8) + >>> out = xp.abs(x) + >>> assert_dtype('abs', x.dtype, out.dtype) + + Or for multiple input dtypes, the expected dtype is inferred from their + resulting type promotion, e.g. + + >>> x1 = xp.arange(5, dtype=xp.uint8) + >>> x2 = xp.arange(5, dtype=xp.uint16) + >>> out = xp.add(x1, x2) + >>> assert_dtype('add', [x1.dtype, x2.dtype], out.dtype) # expected=xp.uint16 + + We can also specify the expected dtype ourselves, e.g. + + >>> x = xp.arange(5, dtype=xp.int8) + >>> out = xp.sum(x) + >>> default_int = xp.asarray(0).dtype + >>> assert_dtype('sum', x, out.dtype, default_int) + + """ in_dtypes = in_dtype if isinstance(in_dtype, Sequence) else [in_dtype] f_in_dtypes = dh.fmt_types(tuple(in_dtypes)) f_out_dtype = dh.dtype_to_name[out_dtype] From c6d59e6a652f03bf1bbe01ef395d1d387766f7aa Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Mon, 16 May 2022 13:11:14 +0100 Subject: [PATCH 2/8] Docstring for `ph.assert_kw_dtype()` --- array_api_tests/pytest_helpers.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index 508e9de0..9d6172b0 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -127,6 +127,14 @@ def assert_dtype( def assert_kw_dtype(func_name: str, kw_dtype: DataType, out_dtype: DataType): + """ + Test the output dtype is the passed keyword dtype, e.g. + + >>> kw = {'dtype': xp.uint8} + >>> out = xp.ones(5, **kw) + >>> assert_kw_dtype('ones', kw['dtype'], out.dtype) + + """ f_kw_dtype = dh.dtype_to_name[kw_dtype] f_out_dtype = dh.dtype_to_name[out_dtype] msg = ( From e01073d8b1b32d9d897333291ccfdf3617d79a51 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Mon, 16 May 2022 13:40:13 +0100 Subject: [PATCH 3/8] Docstrings for default dtype utils --- array_api_tests/pytest_helpers.py | 43 +++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index 9d6172b0..40bbbe2e 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -89,7 +89,7 @@ def assert_dtype( repr_name: str = "out.dtype", ): """ - Tests the output dtype is as expected. + Assert the output dtype is as expected. We infer the expected dtype from in_dtype and to test out_dtype, e.g. @@ -128,7 +128,7 @@ def assert_dtype( def assert_kw_dtype(func_name: str, kw_dtype: DataType, out_dtype: DataType): """ - Test the output dtype is the passed keyword dtype, e.g. + Assert the output dtype is the passed keyword dtype, e.g. >>> kw = {'dtype': xp.uint8} >>> out = xp.ones(5, **kw) @@ -144,33 +144,54 @@ def assert_kw_dtype(func_name: str, kw_dtype: DataType, out_dtype: DataType): assert out_dtype == kw_dtype, msg -def assert_default_float(func_name: str, dtype: DataType): - f_dtype = dh.dtype_to_name[dtype] +def assert_default_float(func_name: str, out_dtype: DataType): + """ + Assert the output dtype is the default float, e.g. + + >>> out = xp.ones(5) + >>> assert_default_float('ones', out.dtype) + + """ + f_dtype = dh.dtype_to_name[out_dtype] f_default = dh.dtype_to_name[dh.default_float] msg = ( f"out.dtype={f_dtype}, should be default " f"floating-point dtype {f_default} [{func_name}()]" ) - assert dtype == dh.default_float, msg + assert out_dtype == dh.default_float, msg + + +def assert_default_int(func_name: str, out_dtype: DataType): + """ + Assert the output dtype is the default int, e.g. + >>> out = xp.full(5, 42) + >>> assert_default_int('full', out.dtype) -def assert_default_int(func_name: str, dtype: DataType): - f_dtype = dh.dtype_to_name[dtype] + """ + f_dtype = dh.dtype_to_name[out_dtype] f_default = dh.dtype_to_name[dh.default_int] msg = ( f"out.dtype={f_dtype}, should be default " f"integer dtype {f_default} [{func_name}()]" ) - assert dtype == dh.default_int, msg + assert out_dtype == dh.default_int, msg + +def assert_default_index(func_name: str, out_dtype: DataType, repr_name="out.dtype"): + """ + Assert the output dtype is the default index dtype, e.g. + + >>> out = xp.argmax() + >>> assert_default_int('argmax', out.dtype) -def assert_default_index(func_name: str, dtype: DataType, repr_name="out.dtype"): - f_dtype = dh.dtype_to_name[dtype] + """ + f_dtype = dh.dtype_to_name[out_dtype] msg = ( f"{repr_name}={f_dtype}, should be the default index dtype, " f"which is either int32 or int64 [{func_name}()]" ) - assert dtype in (xp.int32, xp.int64), msg + assert out_dtype in (xp.int32, xp.int64), msg def assert_shape( From d8c25e3b1c03a9249f6845671cf1efe0ec77acf7 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Mon, 16 May 2022 16:33:30 +0100 Subject: [PATCH 4/8] Docs for shape assertion utils --- array_api_tests/pytest_helpers.py | 36 ++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index 40bbbe2e..f4487174 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -91,19 +91,28 @@ def assert_dtype( """ Assert the output dtype is as expected. - We infer the expected dtype from in_dtype and to test out_dtype, e.g. + If expected=None, we infer the expected dtype as in_dtype, to test + out_dtype, e.g. >>> x = xp.arange(5, dtype=xp.uint8) >>> out = xp.abs(x) >>> assert_dtype('abs', x.dtype, out.dtype) + is equivalent to + + >>> assert out.dtype == xp.uint8 + Or for multiple input dtypes, the expected dtype is inferred from their resulting type promotion, e.g. >>> x1 = xp.arange(5, dtype=xp.uint8) >>> x2 = xp.arange(5, dtype=xp.uint16) >>> out = xp.add(x1, x2) - >>> assert_dtype('add', [x1.dtype, x2.dtype], out.dtype) # expected=xp.uint16 + >>> assert_dtype('add', [x1.dtype, x2.dtype], out.dtype) + + is equivalent to + + >>> assert out.dtype == xp.uint16 We can also specify the expected dtype ourselves, e.g. @@ -182,7 +191,7 @@ def assert_default_index(func_name: str, out_dtype: DataType, repr_name="out.dty """ Assert the output dtype is the default index dtype, e.g. - >>> out = xp.argmax() + >>> out = xp.argmax(xp.arange(5)) >>> assert_default_int('argmax', out.dtype) """ @@ -202,6 +211,13 @@ def assert_shape( repr_name="out.shape", **kw, ): + """ + Assert the output shape is as expected, e.g. + + >>> out = xp.ones((3, 3, 3)) + >>> assert_shape('ones', out.shape, (3, 3, 3)) + + """ if isinstance(out_shape, int): out_shape = (out_shape,) if isinstance(expected, int): @@ -222,6 +238,20 @@ def assert_result_shape( repr_name="out.shape", **kw, ): + """ + Assert the output shape is as expected. + + If expected=None, we infer the expected shape as the result of broadcasting + in_shapes, to test against out_shape, e.g. + + >>> out = xp.add(xp.ones((3, 1)), xp.ones((1, 3))) + >>> assert_shape('add', [(3, 1), (1, 3)], out.shape) + + is equivalent to + + >>> assert out.shape == (3, 3) + + """ if expected is None: expected = sh.broadcast_shapes(*in_shapes) f_in_shapes = " . ".join(str(s) for s in in_shapes) From de3594851f5b28b9c50ef49b29cb0d292478ee75 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Mon, 16 May 2022 17:29:42 +0100 Subject: [PATCH 5/8] Swap `{in/out}_shape` params in `ph.assert_keepdimable_shape()` Also documents it --- array_api_tests/pytest_helpers.py | 17 ++++++++++++++++- array_api_tests/test_searching_functions.py | 4 ++-- array_api_tests/test_statistical_functions.py | 14 +++++++------- array_api_tests/test_utility_functions.py | 4 ++-- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index f4487174..515803ca 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -264,13 +264,28 @@ def assert_result_shape( def assert_keepdimable_shape( func_name: str, - out_shape: Shape, in_shape: Shape, + out_shape: Shape, axes: Tuple[int, ...], keepdims: bool, /, **kw, ): + """ + Assert the output shape from a keepdimable function is as expected, e.g. + + >>> x = xp.asarray([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) + >>> out1 = xp.max(x, keepdims=False) + >>> out2 = xp.max(x, keepdims=True) + >>> assert_keepdimable_shape('max', x.shape, out1.shape, (0, 1), False) + >>> assert_keepdimable_shape('max', x.shape, out2.shape, (0, 1), True) + + is equivalent to + + >>> assert out1.shape == () + >>> assert out2.shape == (1, 1) + + """ if keepdims: shape = tuple(1 if axis in axes else side for axis, side in enumerate(in_shape)) else: diff --git a/array_api_tests/test_searching_functions.py b/array_api_tests/test_searching_functions.py index e679db73..6b134bb0 100644 --- a/array_api_tests/test_searching_functions.py +++ b/array_api_tests/test_searching_functions.py @@ -34,7 +34,7 @@ def test_argmax(x, data): ph.assert_default_index("argmax", out.dtype) axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "argmax", out.shape, x.shape, axes, kw.get("keepdims", False), **kw + "argmax", x.shape, out.shape, axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(x.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, axes), sh.ndindex(out.shape)): @@ -69,7 +69,7 @@ def test_argmin(x, data): ph.assert_default_index("argmin", out.dtype) axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "argmin", out.shape, x.shape, axes, kw.get("keepdims", False), **kw + "argmin", x.shape, out.shape, axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(x.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, axes), sh.ndindex(out.shape)): diff --git a/array_api_tests/test_statistical_functions.py b/array_api_tests/test_statistical_functions.py index c7d0e842..5b019a19 100644 --- a/array_api_tests/test_statistical_functions.py +++ b/array_api_tests/test_statistical_functions.py @@ -38,7 +38,7 @@ def test_max(x, data): ph.assert_dtype("max", x.dtype, out.dtype) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "max", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "max", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(out.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): @@ -67,7 +67,7 @@ def test_mean(x, data): ph.assert_dtype("mean", x.dtype, out.dtype) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "mean", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "mean", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) # Values testing mean is too finicky @@ -88,7 +88,7 @@ def test_min(x, data): ph.assert_dtype("min", x.dtype, out.dtype) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "min", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "min", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(out.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): @@ -147,7 +147,7 @@ def test_prod(x, data): ph.assert_dtype("prod", x.dtype, out.dtype, _dtype) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "prod", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "prod", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(out.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): @@ -194,7 +194,7 @@ def test_std(x, data): ph.assert_dtype("std", x.dtype, out.dtype) ph.assert_keepdimable_shape( - "std", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "std", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) # We can't easily test the result(s) as standard deviation methods vary a lot @@ -245,7 +245,7 @@ def test_sum(x, data): ph.assert_dtype("sum", x.dtype, out.dtype, _dtype) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "sum", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "sum", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(out.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): @@ -292,6 +292,6 @@ def test_var(x, data): ph.assert_dtype("var", x.dtype, out.dtype) ph.assert_keepdimable_shape( - "var", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "var", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) # We can't easily test the result(s) as variance methods vary a lot diff --git a/array_api_tests/test_utility_functions.py b/array_api_tests/test_utility_functions.py index 54052355..7c09fb27 100644 --- a/array_api_tests/test_utility_functions.py +++ b/array_api_tests/test_utility_functions.py @@ -24,7 +24,7 @@ def test_all(x, data): ph.assert_dtype("all", x.dtype, out.dtype, xp.bool) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "all", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "all", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(x.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): @@ -49,7 +49,7 @@ def test_any(x, data): ph.assert_dtype("any", x.dtype, out.dtype, xp.bool) _axes = sh.normalise_axis(kw.get("axis", None), x.ndim) ph.assert_keepdimable_shape( - "any", out.shape, x.shape, _axes, kw.get("keepdims", False), **kw + "any", x.shape, out.shape, _axes, kw.get("keepdims", False), **kw ) scalar_type = dh.get_scalar_type(x.dtype) for indices, out_idx in zip(sh.axes_ndindex(x.shape, _axes), sh.ndindex(out.shape)): From 7b5e3abd30185246c0e5836df0781281d3283d36 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Tue, 17 May 2022 10:01:07 +0100 Subject: [PATCH 6/8] Document remaining pytest helpers --- array_api_tests/pytest_helpers.py | 50 ++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index 515803ca..ff001ab4 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -296,6 +296,19 @@ def assert_keepdimable_shape( def assert_0d_equals( func_name: str, x_repr: str, x_val: Array, out_repr: str, out_val: Array, **kw ): + """ + Assert a 0d array is as expected, e.g. + + >>> x = xp.asarray([0, 1, 2]) + >>> res = xp.asarray(x, copy=True) + >>> res[0] = 42 + >>> assert_0d_equals('__setitem__', 'x[0]', x[0], 'x[0]', res[0]) + + is equivalent to + + >>> assert res[0] == x[0] + + """ msg = ( f"{out_repr}={out_val}, but should be {x_repr}={x_val} " f"[{func_name}({fmt_kw(kw)})]" @@ -316,9 +329,21 @@ def assert_scalar_equals( repr_name: str = "out", **kw, ): + """ + Assert a 0d array, convered to a scalar, is as expected, e.g. + + >>> x = xp.ones(5, dtype=xp.uint8) + >>> out = xp.sum(x) + >>> assert_scalar_equals('sum', int, (), int(out), 5) + + is equivalent to + + >>> assert int(out) == 5 + + """ repr_name = repr_name if idx == () else f"{repr_name}[{idx}]" f_func = f"{func_name}({fmt_kw(kw)})" - if type_ is bool or type_ is int: + if type_ in [bool, int]: msg = f"{repr_name}={out}, but should be {expected} [{f_func}]" assert out == expected, msg elif math.isnan(expected): @@ -332,6 +357,17 @@ def assert_scalar_equals( def assert_fill( func_name: str, fill_value: Scalar, dtype: DataType, out: Array, /, **kw ): + """ + Assert all elements of an array is as expected, e.g. + + >>> out = xp.full(5, 42, dtype=xp.uint8) + >>> assert_fill('full', 42, xp.uint8, out, 5) + + is equivalent to + + >>> assert xp.all(out == 42) + + """ msg = f"out not filled with {fill_value} [{func_name}({fmt_kw(kw)})]\n{out=}" if math.isnan(fill_value): assert ah.all(ah.isnan(out)), msg @@ -340,6 +376,18 @@ def assert_fill( def assert_array(func_name: str, out: Array, expected: Array, /, **kw): + """ + Assert array is (strictly) as expected, e.g. + + >>> x = xp.arange(5) + >>> out = xp.asarray(x) + >>> assert_array('asarray', out, x) + + is equivalent to + + >>> assert xp.all(out == x) + + """ assert_dtype(func_name, out.dtype, expected.dtype) assert_shape(func_name, out.shape, expected.shape, **kw) f_func = f"[{func_name}({fmt_kw(kw)})]" From 4b851ef786ce088d930b340c58ce0cc85e4c9725 Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Tue, 17 May 2022 10:06:07 +0100 Subject: [PATCH 7/8] Remove some use of `array_helpers.py` which just mirrored `xp` funcs The uses which weren't directly imported, i.e. used the alias `ah` --- array_api_tests/pytest_helpers.py | 5 ++--- array_api_tests/test_creation_functions.py | 21 +++++++++--------- ...est_operators_and_elementwise_functions.py | 22 +++++++++---------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/array_api_tests/pytest_helpers.py b/array_api_tests/pytest_helpers.py index ff001ab4..39513670 100644 --- a/array_api_tests/pytest_helpers.py +++ b/array_api_tests/pytest_helpers.py @@ -3,7 +3,6 @@ from typing import Any, Dict, Optional, Sequence, Tuple, Union from . import _array_module as xp -from . import array_helpers as ah from . import dtype_helpers as dh from . import shape_helpers as sh from . import stubs @@ -370,9 +369,9 @@ def assert_fill( """ msg = f"out not filled with {fill_value} [{func_name}({fmt_kw(kw)})]\n{out=}" if math.isnan(fill_value): - assert ah.all(ah.isnan(out)), msg + assert xp.all(xp.isnan(out)), msg else: - assert ah.all(ah.equal(out, ah.asarray(fill_value, dtype=dtype))), msg + assert xp.all(xp.equal(out, xp.asarray(fill_value, dtype=dtype))), msg def assert_array(func_name: str, out: Array, expected: Array, /, **kw): diff --git a/array_api_tests/test_creation_functions.py b/array_api_tests/test_creation_functions.py index a27afb12..f5cb6342 100644 --- a/array_api_tests/test_creation_functions.py +++ b/array_api_tests/test_creation_functions.py @@ -7,7 +7,6 @@ from hypothesis import strategies as st from . import _array_module as xp -from . import array_helpers as ah from . import dtype_helpers as dh from . import hypothesis_helpers as hh from . import pytest_helpers as ph @@ -181,12 +180,12 @@ def test_arange(dtype, data): if dh.is_int_dtype(_dtype): elements = list(r) assume(out.size == len(elements)) - ah.assert_exactly_equal(out, ah.asarray(elements, dtype=_dtype)) + ph.assert_array("arange", out, xp.asarray(elements, dtype=_dtype)) else: assume(out.size == size) if out.size > 0: - assert ah.equal( - out[0], ah.asarray(_start, dtype=out.dtype) + assert xp.equal( + out[0], xp.asarray(_start, dtype=out.dtype) ), f"out[0]={out[0]}, but should be {_start} {f_func}" @@ -421,8 +420,8 @@ def test_linspace(num, dtype, endpoint, data): start = data.draw(xps.from_dtype(_dtype, **finite_kw), label="start") stop = data.draw(xps.from_dtype(_dtype, **finite_kw), label="stop") # avoid overflow errors - assume(not ah.isnan(ah.asarray(stop - start, dtype=_dtype))) - assume(not ah.isnan(ah.asarray(start - stop, dtype=_dtype))) + assume(not xp.isnan(xp.asarray(stop - start, dtype=_dtype))) + assume(not xp.isnan(xp.asarray(start - stop, dtype=_dtype))) kw = data.draw( hh.specified_kwargs( @@ -440,20 +439,20 @@ def test_linspace(num, dtype, endpoint, data): ph.assert_shape("linspace", out.shape, num, start=stop, stop=stop, num=num) f_func = f"[linspace({start}, {stop}, {num})]" if num > 0: - assert ah.equal( - out[0], ah.asarray(start, dtype=out.dtype) + assert xp.equal( + out[0], xp.asarray(start, dtype=out.dtype) ), f"out[0]={out[0]}, but should be {start} {f_func}" if endpoint: if num > 1: - assert ah.equal( - out[-1], ah.asarray(stop, dtype=out.dtype) + assert xp.equal( + out[-1], xp.asarray(stop, dtype=out.dtype) ), f"out[-1]={out[-1]}, but should be {stop} {f_func}" else: # linspace(..., num, endpoint=True) should return an array equivalent to # the first num elements when endpoint=False expected = xp.linspace(start, stop, num + 1, dtype=dtype, endpoint=True) expected = expected[:-1] - ah.assert_exactly_equal(out, expected) + ph.assert_array("linspace", out, expected) @given(dtype=xps.numeric_dtypes(), data=st.data()) diff --git a/array_api_tests/test_operators_and_elementwise_functions.py b/array_api_tests/test_operators_and_elementwise_functions.py index 2c9da2b9..beff36de 100644 --- a/array_api_tests/test_operators_and_elementwise_functions.py +++ b/array_api_tests/test_operators_and_elementwise_functions.py @@ -409,7 +409,7 @@ def func(l: Array, r: Union[Scalar, Array]) -> Array: def func(l: Array, r: Union[Scalar, Array]) -> Array: locals_ = {} - locals_[left_sym] = ah.asarray(l, copy=True) # prevents mutating l + locals_[left_sym] = xp.asarray(l, copy=True) # prevents mutating l locals_[right_sym] = r exec(expr, locals_) return locals_[left_sym] @@ -659,7 +659,7 @@ def test_bitwise_left_shift(ctx, data): if ctx.right_is_scalar: assume(right >= 0) else: - assume(not ah.any(ah.isnegative(right))) + assume(not xp.any(ah.isnegative(right))) res = ctx.func(left, right) @@ -718,7 +718,7 @@ def test_bitwise_right_shift(ctx, data): if ctx.right_is_scalar: assume(right >= 0) else: - assume(not ah.any(ah.isnegative(right))) + assume(not xp.any(ah.isnegative(right))) res = ctx.func(left, right) @@ -851,13 +851,13 @@ def test_floor(x): @given(data=st.data()) def test_floor_divide(ctx, data): left = data.draw( - ctx.left_strat.filter(lambda x: not ah.any(x == 0)), label=ctx.left_sym + ctx.left_strat.filter(lambda x: not xp.any(x == 0)), label=ctx.left_sym ) right = data.draw(ctx.right_strat, label=ctx.right_sym) if ctx.right_is_scalar: assume(right != 0) else: - assume(not ah.any(right == 0)) + assume(not xp.any(right == 0)) res = ctx.func(left, right) @@ -908,7 +908,7 @@ def test_greater_equal(ctx, data): @given(xps.arrays(dtype=xps.numeric_dtypes(), shape=hh.shapes())) def test_isfinite(x): - out = ah.isfinite(x) + out = xp.isfinite(x) ph.assert_dtype("isfinite", x.dtype, out.dtype, xp.bool) ph.assert_shape("isfinite", out.shape, x.shape) unary_assert_against_refimpl("isfinite", x, out, math.isfinite, res_stype=bool) @@ -924,7 +924,7 @@ def test_isinf(x): @given(xps.arrays(dtype=xps.numeric_dtypes(), shape=hh.shapes())) def test_isnan(x): - out = ah.isnan(x) + out = xp.isnan(x) ph.assert_dtype("isnan", x.dtype, out.dtype, xp.bool) ph.assert_shape("isnan", out.shape, x.shape) unary_assert_against_refimpl("isnan", x, out, math.isnan, res_stype=bool) @@ -1024,7 +1024,7 @@ def test_logaddexp(x1, x2): @given(*hh.two_mutual_arrays([xp.bool])) def test_logical_and(x1, x2): - out = ah.logical_and(x1, x2) + out = xp.logical_and(x1, x2) ph.assert_dtype("logical_and", [x1.dtype, x2.dtype], out.dtype) ph.assert_result_shape("logical_and", [x1.shape, x2.shape], out.shape) binary_assert_against_refimpl( @@ -1034,7 +1034,7 @@ def test_logical_and(x1, x2): @given(xps.arrays(dtype=xp.bool, shape=hh.shapes())) def test_logical_not(x): - out = ah.logical_not(x) + out = xp.logical_not(x) ph.assert_dtype("logical_not", x.dtype, out.dtype) ph.assert_shape("logical_not", out.shape, x.shape) unary_assert_against_refimpl( @@ -1044,7 +1044,7 @@ def test_logical_not(x): @given(*hh.two_mutual_arrays([xp.bool])) def test_logical_or(x1, x2): - out = ah.logical_or(x1, x2) + out = xp.logical_or(x1, x2) ph.assert_dtype("logical_or", [x1.dtype, x2.dtype], out.dtype) ph.assert_result_shape("logical_or", [x1.shape, x2.shape], out.shape) binary_assert_against_refimpl( @@ -1157,7 +1157,7 @@ def test_remainder(ctx, data): if ctx.right_is_scalar: assume(right != 0) else: - assume(not ah.any(right == 0)) + assume(not xp.any(right == 0)) res = ctx.func(left, right) From b62af64a40f4fd2f7a652dd6408c3a416c106e4d Mon Sep 17 00:00:00 2001 From: Matthew Barber Date: Tue, 17 May 2022 10:15:10 +0100 Subject: [PATCH 8/8] Remove out-dated skip of `test_linspace` for NumPy workflow The bug doesn't matter anymore, as it happens out-of-scope (use of int dtypes) --- .github/workflows/numpy.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/numpy.yml b/.github/workflows/numpy.yml index 5588c51c..91e16828 100644 --- a/.github/workflows/numpy.yml +++ b/.github/workflows/numpy.yml @@ -33,8 +33,6 @@ jobs: # copy not implemented array_api_tests/test_creation_functions.py::test_asarray_arrays - # https://github.com/numpy/numpy/issues/18881 - array_api_tests/test_creation_functions.py::test_linspace # https://github.com/numpy/numpy/issues/20870 array_api_tests/test_data_type_functions.py::test_can_cast # The return dtype for trace is not consistent in the spec