Skip to content

Commit 91dc500

Browse files
committed
Merge branch 'master' into take-fix
2 parents f60471a + 8c8cb69 commit 91dc500

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2438
-813
lines changed

.flake8

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
select = F

.github/workflows/lint.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ jobs:
66
build:
77

88
runs-on: ubuntu-latest
9-
strategy:
10-
matrix:
11-
python-version: [3.8, 3.9]
12-
139
steps:
14-
- uses: actions/checkout@v1
10+
- uses: actions/checkout@v4
1511
- name: Set up Python ${{ matrix.python-version }}
16-
uses: actions/setup-python@v1
12+
uses: actions/setup-python@v5
1713
with:
18-
python-version: ${{ matrix.python-version }}
14+
python-version: "3.10"
1915
- name: Run pre-commit hook
20-
uses: pre-commit/action@v2.0.3
16+
uses: pre-commit/action@v3.0.1

.github/workflows/numpy.yml renamed to .github/workflows/test.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: NumPy Array API
1+
name: Test Array API Strict
22

33
on: [push, pull_request]
44

@@ -22,10 +22,13 @@ jobs:
2222
- name: Install dependencies
2323
run: |
2424
python -m pip install --upgrade pip
25-
python -m pip install numpy==1.26.2
25+
python -m pip install array-api-strict
2626
python -m pip install -r requirements.txt
2727
- name: Run the test suite
2828
env:
29-
ARRAY_API_TESTS_MODULE: numpy.array_api
29+
ARRAY_API_TESTS_MODULE: array_api_strict
30+
ARRAY_API_STRICT_API_VERSION: 2024.12
3031
run: |
31-
pytest -v -rxXfE --ci --skips-file numpy-skips.txt
32+
pytest -v -rxXfE --skips-file array-api-strict-skips.txt array_api_tests/
33+
# We also have internal tests that isn't really necessary for adopters
34+
pytest -v -rxXfE meta_tests/

README.md

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
This is the test suite for array libraries adopting the [Python Array API
44
standard](https://data-apis.org/array-api/latest).
55

6-
Note the suite is still a **work in progress**. Feedback and contributions are
7-
welcome!
6+
Keeping full coverage of the spec is an on-going priority as the Array API evolves.
7+
Feedback and contributions are welcome!
88

99
## Quickstart
1010

@@ -33,11 +33,29 @@ You need to specify the array library to test. It can be specified via the
3333
`ARRAY_API_TESTS_MODULE` environment variable, e.g.
3434

3535
```bash
36-
$ export ARRAY_API_TESTS_MODULE=numpy.array_api
36+
$ export ARRAY_API_TESTS_MODULE=array_api_strict
37+
```
38+
39+
To specify a runtime-defined module, define `xp` using the `exec('...')` syntax:
40+
41+
```bash
42+
$ export ARRAY_API_TESTS_MODULE="exec('import quantity_array, numpy; xp = quantity_array.quantity_namespace(numpy)')"
3743
```
3844

3945
Alternately, import/define the `xp` variable in `array_api_tests/__init__.py`.
4046

47+
### Specifying the API version
48+
49+
You can specify the API version to use when testing via the
50+
`ARRAY_API_TESTS_VERSION` environment variable, e.g.
51+
52+
```bash
53+
$ export ARRAY_API_TESTS_VERSION="2023.12"
54+
```
55+
56+
Currently this defaults to the array module's `__array_api_version__` value, and
57+
if that attribute doesn't exist then we fallback to `"2021.12"`.
58+
4159
### Run the suite
4260

4361
Simply run `pytest` against the `array_api_tests/` folder to run the full suite.
@@ -138,9 +156,9 @@ issues](https://github.com/data-apis/array-api-tests/issues/) to us.
138156

139157
## Running on CI
140158

141-
See our existing [GitHub Actions workflow for
142-
Numpy](https://github.com/data-apis/array-api-tests/blob/master/.github/workflows/numpy.yml)
143-
for an example of using the test suite on CI.
159+
See our existing [GitHub Actions workflow for `array-api-strict`](https://github.com/data-apis/array-api-tests/blob/master/.github/workflows/test.yml)
160+
for an example of using the test suite on CI. Note [`array-api-strict`](https://github.com/data-apis/array-api-strict)
161+
is an implementation of the array API that uses NumPy under the hood.
144162

145163
### Releases
146164

@@ -154,19 +172,6 @@ library to fail.
154172

155173
### Configuration
156174

157-
#### API version
158-
159-
You can specify the API version to use when testing via the
160-
`ARRAY_API_TESTS_VERSION` environment variable. Currently this defaults to the
161-
array module's `__array_api_version__` value, and if that attribute doesn't
162-
exist then we fallback to `"2021.12"`.
163-
164-
#### CI flag
165-
166-
Use the `--ci` flag to run only the primary and special cases tests. You can
167-
ignore the other test cases as they are redundant for the purposes of checking
168-
compliance.
169-
170175
#### Data-dependent shapes
171176

172177
Use the `--disable-data-dependent-shapes` flag to skip testing functions which have
@@ -260,7 +265,7 @@ jobs:
260265
> There are several ways to avoid this problem:
261266
>
262267
> - Increase the maximum number of examples, e.g., by adding `--max-examples
263-
> 200` to the test command (the default is `100`, see below). This will
268+
> 200` to the test command (the default is `20`, see below). This will
264269
> make it more likely that the failing case will be found, but it will also
265270
> make the tests take longer to run.
266271
> - Don't use `-o xfail_strict=True`. This will make it so that if an XFAIL
@@ -281,11 +286,44 @@ jobs:
281286
The tests make heavy use
282287
[Hypothesis](https://hypothesis.readthedocs.io/en/latest/). You can configure
283288
how many examples are generated using the `--max-examples` flag, which
284-
defaults to `100`. Lower values can be useful for quick checks, and larger
289+
defaults to `20`. Lower values can be useful for quick checks, and larger
285290
values should result in more rigorous runs. For example, `--max-examples
286291
10_000` may find bugs where default runs don't but will take much longer to
287292
run.
288293

294+
#### Skipping Dtypes
295+
296+
The test suite will automatically skip testing of inessential dtypes if they
297+
are not present on the array module namespace, but dtypes can also be skipped
298+
manually by setting the environment variable `ARRAY_API_TESTS_SKIP_DTYPES` to
299+
a comma separated list of dtypes to skip. For example
300+
301+
```
302+
ARRAY_API_TESTS_SKIP_DTYPES=uint16,uint32,uint64 pytest array_api_tests/
303+
```
304+
305+
Note that skipping certain essential dtypes such as `bool` and the default
306+
floating-point dtype is not supported.
307+
308+
#### Turning xfails into skips
309+
310+
Keeping a large number of ``xfails`` can have drastic effects on the run time. This is due
311+
to the way `hypothesis` works: when it detects a failure, it does a large amount
312+
of work to simplify the failing example.
313+
If the run time of the test suite becomes a problem, you can use the
314+
``ARRAY_API_TESTS_XFAIL_MARK`` environment variable: setting it to ``skip`` skips the
315+
entries from the ``xfail.txt`` file instead of xfailing them. Anecdotally, we saw
316+
speed-ups by a factor of 4-5---which allowed us to use 4-5 larger values of
317+
``--max-examples`` within the same time budget.
318+
319+
#### Limiting the array sizes
320+
321+
The test suite generates random arrays as inputs to functions it tests. "unvectorized"
322+
tests iterate over elements of arrays, which might be slow. If the run time becomes
323+
a problem, you can limit the maximum number of elements in generated arrays by
324+
setting the environment variable ``ARRAY_API_TESTS_MAX_ARRAY_SIZE`` to the
325+
desired value. By default, it is set to 1024.
326+
289327
290328
## Contributing
291329
@@ -355,26 +393,6 @@ into a release. If you want, you can add release notes, which GitHub can
355393
generate for you.
356394
357395
358-
## Future plans
359-
360-
Keeping full coverage of the spec is an on-going priority as the Array API
361-
evolves.
362-
363-
Additionally, we have features and general improvements planned. Work on such
364-
functionality is guided primarily by the concerete needs of developers
365-
implementing and using the Array API—be sure to [let us
366-
know](https://github.com/data-apis/array-api-tests/issues) any limitations you
367-
come across.
368-
369-
* A dependency graph for every test case, which could be used to modify pytest's
370-
collection so that low-dependency tests are run first, and tests with faulty
371-
dependencies would skip/xfail.
372-
373-
* In some tests we've found it difficult to find appropaite assertion parameters
374-
for output values (particularly epsilons for floating-point outputs), so we
375-
need to review these and either implement assertions or properly note the lack
376-
thereof.
377-
378396
---
379397
380398
<sup>1</sup>The only exceptions to having just one primary test per function are:

array-api

Submodule array-api updated 121 files
Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,13 @@
1-
# copy not implemented
2-
array_api_tests/test_creation_functions.py::test_asarray_arrays
3-
# https://github.com/numpy/numpy/issues/20870
4-
array_api_tests/test_data_type_functions.py::test_can_cast
5-
# The return dtype for trace is not consistent in the spec
6-
# https://github.com/data-apis/array-api/issues/202#issuecomment-952529197
7-
array_api_tests/test_linalg.py::test_trace
8-
# waiting on NumPy to allow/revert distinct NaNs for np.unique
9-
# https://github.com/numpy/numpy/issues/20326#issuecomment-1012380448
10-
array_api_tests/test_set_functions.py
11-
12-
# newaxis not included in numpy namespace as of v1.26.2
13-
array_api_tests/test_constants.py::test_newaxis
14-
15-
# linalg.solve issue in numpy.array_api as of v1.26.2 (see numpy#25146)
16-
array_api_tests/test_linalg.py::test_solve
17-
# numpy.array_api needs updating... or replaced on CI
18-
array_api_tests/test_linalg.py::test_cross
19-
20-
# https://github.com/numpy/numpy/issues/21373
21-
array_api_tests/test_array_object.py::test_getitem
22-
23-
# missing copy arg
24-
array_api_tests/test_signatures.py::test_func_signature[reshape]
25-
26-
# does not (yet) raise an exception for zero-dimensional inputs to nonzero
27-
array_api_tests/test_searching_functions.py::test_nonzero_zerodim_error
28-
29-
# https://github.com/numpy/numpy/issues/21211
30-
array_api_tests/test_special_cases.py::test_iop[__iadd__(x1_i is -0 and x2_i is -0) -> -0]
1+
# Known special case issue in NumPy. Not worth working around here
312
# https://github.com/numpy/numpy/issues/21213
323
array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i is -infinity and x2_i > 0 and not (x2_i.is_integer() and x2_i % 2 == 1)) -> +infinity]
334
array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i is -0 and x2_i > 0 and not (x2_i.is_integer() and x2_i % 2 == 1)) -> +0]
34-
# noted diversions from spec
5+
6+
# The test suite is incorrectly checking sums that have loss of significance
7+
# (https://github.com/data-apis/array-api-tests/issues/168)
8+
array_api_tests/test_statistical_functions.py::test_sum
9+
10+
# Stubs have a comment: (**note**: libraries may return ``NaN`` to match Python behavior.); Apparently, all libraries do just that
3511
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity]
3612
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity]
3713
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity]
@@ -50,3 +26,9 @@ array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is -infinity
5026
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity]
5127
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0]
5228
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0]
29+
30+
# FIXME needs array-api-strict >=2.3.2
31+
array_api_tests/test_data_type_functions.py::test_finfo
32+
array_api_tests/test_data_type_functions.py::test_finfo_dtype
33+
array_api_tests/test_data_type_functions.py::test_iinfo
34+
array_api_tests/test_data_type_functions.py::test_iinfo_dtype

array_api_tests/__init__.py

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,47 @@
1111

1212

1313
# You can comment the following out and instead import the specific array module
14-
# you want to test, e.g. `import numpy.array_api as xp`.
14+
# you want to test, e.g. `import array_api_strict as xp`.
1515
if "ARRAY_API_TESTS_MODULE" in os.environ:
16-
xp_name = os.environ["ARRAY_API_TESTS_MODULE"]
17-
_module, _sub = xp_name, None
18-
if "." in xp_name:
19-
_module, _sub = xp_name.split(".", 1)
20-
xp = import_module(_module)
21-
if _sub:
22-
try:
23-
xp = getattr(xp, _sub)
24-
except AttributeError:
25-
# _sub may be a submodule that needs to be imported. WE can't
26-
# do this in every case because some array modules are not
27-
# submodules that can be imported (like mxnet.nd).
28-
xp = import_module(xp_name)
16+
env_var = os.environ["ARRAY_API_TESTS_MODULE"]
17+
if env_var.startswith("exec('") and env_var.endswith("')"):
18+
script = env_var[6:][:-2]
19+
namespace = {}
20+
exec(script, namespace)
21+
xp = namespace["xp"]
22+
xp_name = xp.__name__
23+
else:
24+
xp_name = env_var
25+
_module, _sub = xp_name, None
26+
if "." in xp_name:
27+
_module, _sub = xp_name.split(".", 1)
28+
xp = import_module(_module)
29+
if _sub:
30+
try:
31+
xp = getattr(xp, _sub)
32+
except AttributeError:
33+
# _sub may be a submodule that needs to be imported. We can't
34+
# do this in every case because some array modules are not
35+
# submodules that can be imported (like mxnet.nd).
36+
xp = import_module(xp_name)
2937
else:
3038
raise RuntimeError(
3139
"No array module specified - either edit __init__.py or set the "
3240
"ARRAY_API_TESTS_MODULE environment variable."
3341
)
3442

3543

44+
# If xp.bool is not available, like in some versions of NumPy and CuPy, try
45+
# patching in xp.bool_.
46+
try:
47+
xp.bool
48+
except AttributeError as e:
49+
if hasattr(xp, "bool_"):
50+
xp.bool = xp.bool_
51+
else:
52+
raise e
53+
54+
3655
# We monkey patch floats() to always disable subnormals as they are out-of-scope
3756

3857
_floats = st.floats
@@ -67,7 +86,7 @@ def _from_dtype(*a, **kw):
6786

6887

6988
api_version = os.getenv(
70-
"ARRAY_API_TESTS_VERSION", getattr(xp, "__array_api_version__", "2021.12")
89+
"ARRAY_API_TESTS_VERSION", getattr(xp, "__array_api_version__", "2024.12")
7190
)
7291
xps = array_api.make_strategies_namespace(xp, api_version=api_version)
7392

array_api_tests/array_helpers.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from ._array_module import (isnan, all, any, equal, not_equal, logical_and,
2-
logical_or, isfinite, greater, less, less_equal,
2+
logical_or, isfinite, greater, less_equal,
33
zeros, ones, full, bool, int8, int16, int32,
44
int64, uint8, uint16, uint32, uint64, float32,
55
float64, nan, inf, pi, remainder, divide, isinf,
@@ -164,6 +164,16 @@ def notequal(x, y):
164164

165165
return not_equal(x, y)
166166

167+
def less(x, y):
168+
"""
169+
Same as less(x, y) except it allows comparing uint64 with signed int dtypes
170+
"""
171+
if x.dtype == uint64 and dh.dtype_signed[y.dtype]:
172+
return xp.where(y < 0, xp.asarray(False), xp.less(x, xp.astype(y, uint64)))
173+
if y.dtype == uint64 and dh.dtype_signed[x.dtype]:
174+
return xp.where(x < 0, xp.asarray(True), xp.less(xp.astype(x, uint64), y))
175+
return xp.less(x, y)
176+
167177
def assert_exactly_equal(x, y, msg_extra=None):
168178
"""
169179
Test that the arrays x and y are exactly equal.

0 commit comments

Comments
 (0)