Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12", "3.13", "3.14"]

python-version: ["3.10", "3.12", "3.13", "3.14"]
steps:
- name: Checkout array-api-tests
uses: actions/checkout@v1
Expand Down
21 changes: 21 additions & 0 deletions array_api_tests/pytest_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .typing import Array, DataType, Scalar, ScalarType, Shape

__all__ = [
"add_note",
"raises",
"doesnt_raise",
"nargs",
Expand All @@ -31,6 +32,26 @@
]


def add_note(exc, note):
"""
Add a note to an exception in a backward-compatible way.

For Python 3.11+, this uses the built-in exc.add_note() method.
For earlier versions, it manually appends to exc.__notes__.

https://github.com/HypothesisWorks/hypothesis/issues/4606#issuecomment-3568140174
"""
try:
exc.add_note(note)
except AttributeError:
if not hasattr(exc, "__notes__"):
try:
exc.__notes__ = []
except AttributeError:
return # give up, might be e.g. a frozen dataclass
exc.__notes__.append(note)


def raises(exceptions, function, message=""):
"""
Like pytest.raises() except it allows custom error messages
Expand Down
2 changes: 1 addition & 1 deletion array_api_tests/test_array_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def test_getitem(shape, dtype, data):
expected = xp.asarray(out_obj, dtype=dtype)
ph.assert_array_elements("__getitem__", out=out, expected=expected)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

@pytest.mark.unvectorized
Expand Down
28 changes: 14 additions & 14 deletions array_api_tests/test_creation_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def test_arange(dtype, data):
out[0], xp.asarray(_start, dtype=out.dtype)
), f"out[0]={out[0]}, but should be {_start} {f_func}"
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand Down Expand Up @@ -257,7 +257,7 @@ def test_asarray_scalars(shape, data):
v = scalar_type(out[idx])
ph.assert_scalar_equals("asarray", type_=scalar_type, idx=idx, out=v, expected=v_expect, kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

def scalar_eq(s1: Scalar, s2: Scalar) -> bool:
Expand Down Expand Up @@ -323,7 +323,7 @@ def test_asarray_arrays(shape, dtypes, data):
new_out_value, value
), f"{f_out}, but should be {value} after x was mutated"
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -339,7 +339,7 @@ def test_empty(shape, kw):
ph.assert_kw_dtype("empty", kw_dtype=kw["dtype"], out_dtype=out.dtype)
ph.assert_shape("empty", out_shape=out.shape, expected=shape, kw=dict(shape=shape))
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -357,7 +357,7 @@ def test_empty_like(x, kw):
ph.assert_kw_dtype("empty_like", kw_dtype=kw["dtype"], out_dtype=out.dtype)
ph.assert_shape("empty_like", out_shape=out.shape, expected=x.shape)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

@given(
Expand Down Expand Up @@ -387,7 +387,7 @@ def test_eye(n_rows, n_cols, kw):
expected = xp.reshape(expected, (n_rows, _n_cols))
ph.assert_array_elements("eye", out=out, expected=expected, kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand Down Expand Up @@ -455,7 +455,7 @@ def test_full(shape, fill_value, kw):
ph.assert_shape("full", out_shape=out.shape, expected=shape, kw=dict(shape=shape))
ph.assert_fill("full", fill_value=fill_value, dtype=dtype, out=out, kw=dict(fill_value=fill_value))
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -476,7 +476,7 @@ def test_full_like(kw, data):
ph.assert_shape("full_like", out_shape=out.shape, expected=x.shape)
ph.assert_fill("full_like", fill_value=fill_value, dtype=dtype, out=out, kw=dict(fill_value=fill_value))
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

finite_kw = {"allow_nan": False, "allow_infinity": False}
Expand Down Expand Up @@ -534,7 +534,7 @@ def test_linspace(num, dtype, endpoint, data):
expected = expected[:-1]
ph.assert_array_elements("linspace", out=out, expected=expected)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand Down Expand Up @@ -563,7 +563,7 @@ def test_meshgrid(dtype, data):
for i, x in enumerate(out):
ph.assert_dtype("meshgrid", in_dtype=dtype, out_dtype=x.dtype, repr_name=f"out[{i}].dtype")
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -590,7 +590,7 @@ def test_ones(shape, kw):
dtype = kw.get("dtype", None) or dh.default_float
ph.assert_fill("ones", fill_value=make_one(dtype), dtype=dtype, out=out, kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -611,7 +611,7 @@ def test_ones_like(x, kw):
ph.assert_fill("ones_like", fill_value=make_one(dtype), dtype=dtype,
out=out, kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -638,7 +638,7 @@ def test_zeros(shape, kw):
ph.assert_fill("zeros", fill_value=make_zero(dtype), dtype=dtype, out=out,
kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -660,5 +660,5 @@ def test_zeros_like(x, kw):
ph.assert_fill("zeros_like", fill_value=make_zero(dtype), dtype=dtype,
out=out, kw=kw)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise
28 changes: 14 additions & 14 deletions array_api_tests/test_data_type_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def test_astype(x_dtype, dtype, kw, data):
# TODO: test values
# TODO: test copy
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand Down Expand Up @@ -124,7 +124,7 @@ def test_broadcast_arrays(shapes, data):
)
# TODO: test values
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -145,7 +145,7 @@ def test_broadcast_to(x, data):
ph.assert_shape("broadcast_to", out_shape=out.shape, expected=shape)
# TODO: test values
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -168,7 +168,7 @@ def test_can_cast(_from, to):
# check that the array library actually allows such casts.
assert out == expected, f"{out=}, but should be {expected} {f_func}"
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -189,7 +189,7 @@ def test_finfo(dtype):
assert isinstance(out.min, float)
assert isinstance(out.smallest_normal, float)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

@pytest.mark.min_version("2022.12")
Expand All @@ -211,7 +211,7 @@ def test_finfo_dtype(dtype):
assert out.dtype is not float
assert out.dtype is not complex
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -230,7 +230,7 @@ def test_iinfo(dtype):
assert isinstance(out.max, int)
assert isinstance(out.min, int)
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -245,7 +245,7 @@ def test_iinfo_dtype(dtype):
assert not isinstance(out.dtype, str)
assert out.dtype is not int
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand Down Expand Up @@ -277,7 +277,7 @@ def test_isdtype(dtype, kind):
break
assert out == expected, f"{out=}, but should be {expected} [isdtype()]"
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise


Expand All @@ -290,7 +290,7 @@ def test_result_type(self, dtypes):
out = xp.result_type(*dtypes)
ph.assert_dtype("result_type", in_dtype=dtypes, out_dtype=out, repr_name="out")
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

@given(pair=hh.pair_of_mutually_promotable_dtypes(None))
Expand All @@ -312,7 +312,7 @@ def test_arrays_and_dtypes(self, pair, data):
out = xp.result_type(*a_and_dt)
ph.assert_dtype("result_type", in_dtype=s1+s2, out_dtype=out, repr_name="out")
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

@given(dtypes=hh.mutually_promotable_dtypes(2), data=st.data())
Expand All @@ -333,7 +333,7 @@ def test_with_scalars(self, dtypes, data):
else:
raise ValueError(f"unknown dtype {out = }.")
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

scalar = data.draw(st.sampled_from(scalars))
Expand All @@ -344,7 +344,7 @@ def test_with_scalars(self, dtypes, data):
out_scalar = xp.result_type(*inputs)
assert out_scalar == out
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise

# retry with arrays
Expand All @@ -356,5 +356,5 @@ def test_with_scalars(self, dtypes, data):
out_scalar = xp.result_type(*inputs)
assert out_scalar == out
except Exception as exc:
exc.add_note(repro_snippet)
ph.add_note(exc, repro_snippet)
raise
Loading