array-api-strict 2.4__tar.gz → 2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/array-api-tests.yml +15 -9
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/docs-build.yml +3 -3
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/docs-deploy.yml +2 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/publish-package.yml +6 -6
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/ruff.yml +2 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/tests.yml +14 -7
- {array_api_strict-2.4 → array_api_strict-2.5}/CHANGELOG.md +91 -2
- {array_api_strict-2.4/array_api_strict.egg-info → array_api_strict-2.5}/PKG-INFO +4 -1
- {array_api_strict-2.4 → array_api_strict-2.5}/array-api-tests-xfails.txt +16 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/__init__.py +4 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_array_object.py +50 -19
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_creation_functions.py +12 -5
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_data_type_functions.py +16 -4
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_elementwise_functions.py +6 -4
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_flags.py +3 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_info.py +5 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_linalg.py +62 -1
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_manipulation_functions.py +1 -1
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_searching_functions.py +8 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_set_functions.py +23 -1
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_version.py +16 -3
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_array_object.py +93 -27
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_creation_functions.py +2 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_elementwise_functions.py +16 -4
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_flags.py +11 -11
- {array_api_strict-2.4 → array_api_strict-2.5/array_api_strict.egg-info}/PKG-INFO +4 -1
- array_api_strict-2.5/array_api_strict.egg-info/requires.txt +5 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/changelog.md +91 -2
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/index.md +12 -11
- {array_api_strict-2.4 → array_api_strict-2.5}/pyproject.toml +3 -0
- array_api_strict-2.4/array_api_strict.egg-info/requires.txt +0 -1
- {array_api_strict-2.4 → array_api_strict-2.5}/.gitattributes +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/dependabot.yml +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/.github/workflows/dependabot-auto-merge.yml +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/.gitignore +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/LICENSE +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/README.md +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_constants.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_dtypes.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_fft.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_helpers.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_indexing_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_linear_algebra_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_sorting_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_statistical_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_typing.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/_utility_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/py.typed +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/__init__.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/conftest.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_data_type_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_device_support.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_indexing_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_linalg.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_manipulation_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_searching_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_set_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_sorting_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_statistical_functions.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict/tests/test_validation.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict.egg-info/SOURCES.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict.egg-info/dependency_links.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/array_api_strict.egg-info/top_level.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/Makefile +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/_static/custom.css +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/_static/favicon.png +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/api.rst +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/conf.py +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/make.bat +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/releasing.md +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/docs/requirements.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/pytest.ini +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/requirements-dev.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/requirements.txt +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/ruff.toml +0 -0
- {array_api_strict-2.4 → array_api_strict-2.5}/setup.cfg +0 -0
|
@@ -3,33 +3,39 @@ name: Array API Tests
|
|
|
3
3
|
on: [push, pull_request]
|
|
4
4
|
|
|
5
5
|
env:
|
|
6
|
-
PYTEST_ARGS: "-v -rxXfE --hypothesis-disable-deadline --max-examples
|
|
7
|
-
API_VERSIONS: "2023.12 2024.12"
|
|
6
|
+
PYTEST_ARGS: "-v -rxXfE --hypothesis-disable-deadline --max-examples 500 -n 4"
|
|
7
|
+
API_VERSIONS: "2023.12 2024.12 2025.12"
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
array-api-tests:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
strategy:
|
|
13
13
|
matrix:
|
|
14
|
-
python-version: ['3.12', '3.13']
|
|
15
|
-
numpy-version: ['1.26', '2.
|
|
14
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
15
|
+
numpy-version: ['1.26', '2.3.5', 'dev']
|
|
16
16
|
exclude:
|
|
17
|
+
- python-version: '3.10'
|
|
18
|
+
numpy-version: '2.3.5'
|
|
19
|
+
- python-version: '3.10'
|
|
20
|
+
numpy-version: 'dev'
|
|
17
21
|
- python-version: '3.13'
|
|
18
22
|
numpy-version: '1.26'
|
|
19
|
-
|
|
23
|
+
- python-version: '3.14'
|
|
24
|
+
numpy-version: '1.26'
|
|
25
|
+
fail-fast: false
|
|
20
26
|
steps:
|
|
21
27
|
- name: Checkout array-api-strict
|
|
22
|
-
uses: actions/checkout@
|
|
28
|
+
uses: actions/checkout@v6
|
|
23
29
|
with:
|
|
24
30
|
path: array-api-strict
|
|
25
31
|
- name: Checkout array-api-tests
|
|
26
|
-
uses: actions/checkout@
|
|
32
|
+
uses: actions/checkout@v6
|
|
27
33
|
with:
|
|
28
34
|
repository: data-apis/array-api-tests
|
|
29
35
|
submodules: 'true'
|
|
30
36
|
path: array-api-tests
|
|
31
37
|
- name: Set up Python ${{ matrix.python-version }}
|
|
32
|
-
uses: actions/setup-python@
|
|
38
|
+
uses: actions/setup-python@v6
|
|
33
39
|
with:
|
|
34
40
|
python-version: ${{ matrix.python-version }}
|
|
35
41
|
- name: Install Dependencies
|
|
@@ -42,7 +48,7 @@ jobs:
|
|
|
42
48
|
fi
|
|
43
49
|
python -m pip install ${GITHUB_WORKSPACE}/array-api-strict
|
|
44
50
|
python -m pip install -r ${GITHUB_WORKSPACE}/array-api-tests/requirements.txt
|
|
45
|
-
python -m pip install hypothesis
|
|
51
|
+
python -m pip install hypothesis pytest-xdist
|
|
46
52
|
- name: Run the array API testsuite
|
|
47
53
|
env:
|
|
48
54
|
ARRAY_API_TESTS_MODULE: array_api_strict
|
|
@@ -6,8 +6,8 @@ jobs:
|
|
|
6
6
|
docs-build:
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
|
-
- uses: actions/checkout@
|
|
10
|
-
- uses: actions/setup-python@
|
|
9
|
+
- uses: actions/checkout@v6
|
|
10
|
+
- uses: actions/setup-python@v6
|
|
11
11
|
- name: Install Dependencies
|
|
12
12
|
run: |
|
|
13
13
|
python -m pip install -r docs/requirements.txt
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
cd docs
|
|
17
17
|
make html
|
|
18
18
|
- name: Upload Artifact
|
|
19
|
-
uses: actions/upload-artifact@
|
|
19
|
+
uses: actions/upload-artifact@v6
|
|
20
20
|
with:
|
|
21
21
|
name: docs-build
|
|
22
22
|
path: docs/_build/html
|
|
@@ -11,9 +11,9 @@ jobs:
|
|
|
11
11
|
environment:
|
|
12
12
|
name: docs-deploy
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@v6
|
|
15
15
|
- name: Download Artifact
|
|
16
|
-
uses: dawidd6/action-download-artifact@
|
|
16
|
+
uses: dawidd6/action-download-artifact@v14
|
|
17
17
|
with:
|
|
18
18
|
workflow: docs-build.yml
|
|
19
19
|
name: docs-build
|
|
@@ -30,12 +30,12 @@ jobs:
|
|
|
30
30
|
runs-on: ubuntu-latest
|
|
31
31
|
|
|
32
32
|
steps:
|
|
33
|
-
- uses: actions/checkout@
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
34
|
with:
|
|
35
35
|
fetch-depth: 0
|
|
36
36
|
|
|
37
37
|
- name: Set up Python
|
|
38
|
-
uses: actions/setup-python@
|
|
38
|
+
uses: actions/setup-python@v6
|
|
39
39
|
with:
|
|
40
40
|
python-version: '3.x'
|
|
41
41
|
|
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
run: python -m zipfile --list dist/array_api_strict-*.whl
|
|
63
63
|
|
|
64
64
|
- name: Upload distribution artifact
|
|
65
|
-
uses: actions/upload-artifact@
|
|
65
|
+
uses: actions/upload-artifact@v6
|
|
66
66
|
with:
|
|
67
67
|
name: dist-artifact
|
|
68
68
|
path: dist
|
|
@@ -83,7 +83,7 @@ jobs:
|
|
|
83
83
|
|
|
84
84
|
steps:
|
|
85
85
|
- name: Download distribution artifact
|
|
86
|
-
uses: actions/download-artifact@
|
|
86
|
+
uses: actions/download-artifact@v7
|
|
87
87
|
with:
|
|
88
88
|
name: dist-artifact
|
|
89
89
|
path: dist
|
|
@@ -97,14 +97,14 @@ jobs:
|
|
|
97
97
|
# if: >-
|
|
98
98
|
# (github.event_name == 'push' && startsWith(github.ref, 'refs/tags'))
|
|
99
99
|
# || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish == 'true')
|
|
100
|
-
# uses: pypa/gh-action-pypi-publish@v1.
|
|
100
|
+
# uses: pypa/gh-action-pypi-publish@v1.13.0
|
|
101
101
|
# with:
|
|
102
102
|
# repository-url: https://test.pypi.org/legacy/
|
|
103
103
|
# print-hash: true
|
|
104
104
|
|
|
105
105
|
- name: Publish distribution 📦 to PyPI
|
|
106
106
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
|
107
|
-
uses: pypa/gh-action-pypi-publish@v1.
|
|
107
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|
|
108
108
|
with:
|
|
109
109
|
print-hash: true
|
|
110
110
|
|
|
@@ -5,9 +5,9 @@ jobs:
|
|
|
5
5
|
runs-on: ubuntu-latest
|
|
6
6
|
continue-on-error: true
|
|
7
7
|
steps:
|
|
8
|
-
- uses: actions/checkout@
|
|
8
|
+
- uses: actions/checkout@v6
|
|
9
9
|
- name: Install Python
|
|
10
|
-
uses: actions/setup-python@
|
|
10
|
+
uses: actions/setup-python@v6
|
|
11
11
|
with:
|
|
12
12
|
python-version: "3.11"
|
|
13
13
|
- name: Install dependencies
|
|
@@ -5,15 +5,21 @@ jobs:
|
|
|
5
5
|
runs-on: ubuntu-latest
|
|
6
6
|
strategy:
|
|
7
7
|
matrix:
|
|
8
|
-
python-version: ['3.10', '3.11', '3.12', '3.13']
|
|
9
|
-
numpy-version: ['1.26', 'dev']
|
|
8
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
9
|
+
numpy-version: ['1.26', '2.3.5', 'dev']
|
|
10
10
|
exclude:
|
|
11
|
+
- python-version: '3.10'
|
|
12
|
+
numpy-version: '2.3.5'
|
|
13
|
+
- python-version: '3.10'
|
|
14
|
+
numpy-version: 'dev'
|
|
11
15
|
- python-version: '3.13'
|
|
12
16
|
numpy-version: '1.26'
|
|
13
|
-
|
|
17
|
+
- python-version: '3.14'
|
|
18
|
+
numpy-version: '1.26'
|
|
19
|
+
fail-fast: false
|
|
14
20
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-python@
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
|
+
- uses: actions/setup-python@v6
|
|
17
23
|
with:
|
|
18
24
|
python-version: ${{ matrix.python-version }}
|
|
19
25
|
- name: Install Dependencies
|
|
@@ -22,9 +28,10 @@ jobs:
|
|
|
22
28
|
if [[ "${{ matrix.numpy-version }}" == "dev" ]]; then
|
|
23
29
|
python -m pip install --pre --extra-index https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy;
|
|
24
30
|
else
|
|
25
|
-
python -m pip install 'numpy
|
|
31
|
+
python -m pip install 'numpy=='${{ matrix.numpy-version }}
|
|
26
32
|
fi
|
|
27
|
-
python -m pip install
|
|
33
|
+
python -m pip install pytest hypothesis
|
|
34
|
+
python -c'import numpy as np; print(f"{np.__version__ = }")'
|
|
28
35
|
- name: Run Tests
|
|
29
36
|
run: |
|
|
30
37
|
pytest
|
|
@@ -1,6 +1,95 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.5 (2026-02-23)
|
|
4
|
+
|
|
5
|
+
This release targets the 2025.12 revision of the Array API standard, and supports
|
|
6
|
+
Python versions 3.10--3.14.
|
|
7
|
+
|
|
8
|
+
### Major Changes
|
|
9
|
+
|
|
10
|
+
- The default version of the array API standard is now 2025.12. Previous versions can
|
|
11
|
+
still be enabled via the [flags API](array-api-strict-flags), e.g., by calling
|
|
12
|
+
`set_array_api_strict_flags(api_version='2024.12')` or setting
|
|
13
|
+
`ARRAY_API_STRICT_API_VERSION=2024.12`.
|
|
14
|
+
|
|
15
|
+
Note that this support is still relatively undertested. Please [report any
|
|
16
|
+
issues](https://github.com/data-apis/array-api-strict/issues) you find.
|
|
17
|
+
|
|
18
|
+
- The following functions, new in the 2025.12 revision, are implemented:
|
|
19
|
+
|
|
20
|
+
- `isin`
|
|
21
|
+
- `broadcast_shapes`
|
|
22
|
+
- `linalg.eig`
|
|
23
|
+
- `linalg.eigvals`
|
|
24
|
+
|
|
25
|
+
The following updates to existing APIs have been implemented, per the 2025.12 Array API
|
|
26
|
+
standard revision:
|
|
27
|
+
|
|
28
|
+
- `searchsorted` now accepts a python scalar for its second argument,
|
|
29
|
+
`x2`.
|
|
30
|
+
- `expand_dims` now accepts tuples of axes.
|
|
31
|
+
- `permute_dims` now accepts negative axes, with the usual meaning (`axis=-1` is
|
|
32
|
+
the last axis, `-2` is the second-to-last axis, and so on).
|
|
33
|
+
|
|
34
|
+
The following functions now return tuples instead of lists:
|
|
35
|
+
|
|
36
|
+
- `__array_namespace_info__().devices`
|
|
37
|
+
- `broadcast_arrays`
|
|
38
|
+
- `meshgrid`
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
- Array objects can now be pickled.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Minor Changes
|
|
45
|
+
|
|
46
|
+
- Several functions were diverging from the standard, and have been fixed to follow
|
|
47
|
+
the 2025.12 revision of the standard:
|
|
48
|
+
|
|
49
|
+
- `clip` has been updated to accept python `int` scalars for its `min` and `max`
|
|
50
|
+
arguments for clipping a floating-point array.
|
|
51
|
+
- `clip` has been updated to always returns a copy of an input array.
|
|
52
|
+
- `full` and `full_like` now reject array values for the `fill_value` argument.
|
|
53
|
+
- `expand_dims` accepts its axis argument as either positional or keyword argument.
|
|
54
|
+
|
|
55
|
+
- `sign` of a complex zero, `sign(0 + 0j)` has been fixed to return zero.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Contributors
|
|
59
|
+
|
|
60
|
+
The following users contributed to this release:
|
|
61
|
+
|
|
62
|
+
Evgeni Burovski,
|
|
63
|
+
Lucas Colley,
|
|
64
|
+
Lucy Liu
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## 2.4.1 (2025-07-27)
|
|
68
|
+
|
|
69
|
+
### Major Changes
|
|
70
|
+
|
|
71
|
+
- The array object defines `__array__` again when `__buffer__` is not available.
|
|
72
|
+
|
|
73
|
+
- Support for Python versions 3.10 and 3.11 has been reinstated.
|
|
74
|
+
|
|
75
|
+
### Minor Changes
|
|
76
|
+
|
|
77
|
+
- Arithmetic operations no longer accept NumPy arrays.
|
|
78
|
+
|
|
79
|
+
- Disallow `__setitem__` for invalid dtype combinations (e.g. setting a float value
|
|
80
|
+
into an integer array)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### Contributors
|
|
84
|
+
|
|
85
|
+
The following users contributed to this release:
|
|
86
|
+
|
|
87
|
+
Evgeni Burovski,
|
|
88
|
+
Lucas Colley,
|
|
89
|
+
Guido Imperiale
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## 2.4.0 (2025-06-16)
|
|
4
93
|
|
|
5
94
|
### Major Changes
|
|
6
95
|
|
|
@@ -39,7 +128,7 @@ The following users contributed to this release:
|
|
|
39
128
|
|
|
40
129
|
Lumir Balhar,
|
|
41
130
|
Evgeni Burovski,
|
|
42
|
-
Joren Hammudoglu
|
|
131
|
+
Joren Hammudoglu,
|
|
43
132
|
Tim Head,
|
|
44
133
|
Guido Imperiale,
|
|
45
134
|
Lucy Liu
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: array_api_strict
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5
|
|
4
4
|
Summary: A strict, minimal implementation of the Python array API standard.
|
|
5
5
|
Author: Consortium for Python Data API Standards
|
|
6
6
|
License: Copyright (c) 2021-2024, NumPy Developers, Consortium for Python Data API Standards
|
|
@@ -48,6 +48,9 @@ Requires-Python: >=3.10
|
|
|
48
48
|
Description-Content-Type: text/markdown
|
|
49
49
|
License-File: LICENSE
|
|
50
50
|
Requires-Dist: numpy
|
|
51
|
+
Provides-Extra: test
|
|
52
|
+
Requires-Dist: pytest; extra == "test"
|
|
53
|
+
Requires-Dist: hypothesis; extra == "test"
|
|
51
54
|
|
|
52
55
|
# array-api-strict
|
|
53
56
|
|
|
@@ -29,3 +29,19 @@ array_api_tests/test_statistical_functions.py::test_sum
|
|
|
29
29
|
|
|
30
30
|
array_api_tests/test_special_cases.py::test_nan_propagation[cumulative_prod]
|
|
31
31
|
|
|
32
|
+
# complex special cases which failed "forever"
|
|
33
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is +0) -> +infinity + 0j]
|
|
34
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is -infinity and imag(x_i) is +infinity) -> -1 + 0j]
|
|
35
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is +infinity) -> infinity + NaN j]
|
|
36
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is -infinity and imag(x_i) is NaN) -> -1 + 0j]
|
|
37
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is NaN) -> infinity + NaN j]
|
|
38
|
+
array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is NaN and imag(x_i) is +0) -> NaN + 0j]
|
|
39
|
+
array_api_tests/test_special_cases.py::test_unary[expm1((real(x_i) is +0 or real(x_i) == -0) and imag(x_i) is +0) -> 0 + 0j]
|
|
40
|
+
|
|
41
|
+
array_api_tests/test_special_cases.py::test_unary[sign((real(x_i) is -0 or real(x_i) == +0) and (imag(x_i) is -0 or imag(x_i) == +0)) -> 0 + 0j]
|
|
42
|
+
array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> 1 + 0j]
|
|
43
|
+
|
|
44
|
+
# this acosh failure is only seen with python==3.10 and numpy==2.2.6, and not e.g. python 3.12 & numpy 2.4.1
|
|
45
|
+
array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is +0 and imag(x_i) is NaN) -> NaN \xb1 \u03c0j/2]
|
|
46
|
+
|
|
47
|
+
array_api_tests/test_special_cases.py::test_unary[sqrt(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +0 + infinity j]
|
|
@@ -73,6 +73,7 @@ __all__ += [
|
|
|
73
73
|
from ._data_type_functions import (
|
|
74
74
|
astype,
|
|
75
75
|
broadcast_arrays,
|
|
76
|
+
broadcast_shapes,
|
|
76
77
|
broadcast_to,
|
|
77
78
|
can_cast,
|
|
78
79
|
finfo,
|
|
@@ -84,6 +85,7 @@ from ._data_type_functions import (
|
|
|
84
85
|
__all__ += [
|
|
85
86
|
"astype",
|
|
86
87
|
"broadcast_arrays",
|
|
88
|
+
"broadcast_shapes",
|
|
87
89
|
"broadcast_to",
|
|
88
90
|
"can_cast",
|
|
89
91
|
"finfo",
|
|
@@ -299,9 +301,9 @@ from ._searching_functions import argmax, argmin, nonzero, count_nonzero, search
|
|
|
299
301
|
|
|
300
302
|
__all__ += ["argmax", "argmin", "nonzero", "count_nonzero", "searchsorted", "where"]
|
|
301
303
|
|
|
302
|
-
from ._set_functions import unique_all, unique_counts, unique_inverse, unique_values
|
|
304
|
+
from ._set_functions import unique_all, unique_counts, unique_inverse, unique_values, isin
|
|
303
305
|
|
|
304
|
-
__all__ += ["unique_all", "unique_counts", "unique_inverse", "unique_values"]
|
|
306
|
+
__all__ += ["unique_all", "unique_counts", "unique_inverse", "unique_values", "isin"]
|
|
305
307
|
|
|
306
308
|
from ._sorting_functions import argsort, sort
|
|
307
309
|
|
|
@@ -16,10 +16,11 @@ of ndarray.
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import operator
|
|
19
|
+
import sys
|
|
19
20
|
from collections.abc import Iterator
|
|
20
21
|
from enum import IntEnum
|
|
21
22
|
from types import EllipsisType, ModuleType
|
|
22
|
-
from typing import Any, Final, Literal, SupportsIndex
|
|
23
|
+
from typing import Any, Final, Literal, SupportsIndex, Callable
|
|
23
24
|
|
|
24
25
|
import numpy as np
|
|
25
26
|
import numpy.typing as npt
|
|
@@ -67,8 +68,6 @@ class Device:
|
|
|
67
68
|
CPU_DEVICE = Device()
|
|
68
69
|
ALL_DEVICES = (CPU_DEVICE, Device("device1"), Device("device2"))
|
|
69
70
|
|
|
70
|
-
_default = object()
|
|
71
|
-
|
|
72
71
|
|
|
73
72
|
class Array:
|
|
74
73
|
"""
|
|
@@ -126,6 +125,9 @@ class Array:
|
|
|
126
125
|
raise TypeError(
|
|
127
126
|
"The array_api_strict Array object should not be instantiated directly. Use an array creation function, such as asarray(), instead."
|
|
128
127
|
)
|
|
128
|
+
|
|
129
|
+
def __reduce__(self) -> tuple[Callable, tuple[npt.NDArray[Any], Device]]:
|
|
130
|
+
return (self._new, (self._array, self._device))
|
|
129
131
|
|
|
130
132
|
# These functions are not required by the spec, but are implemented for
|
|
131
133
|
# the sake of usability.
|
|
@@ -149,29 +151,40 @@ class Array:
|
|
|
149
151
|
|
|
150
152
|
__str__ = __repr__
|
|
151
153
|
|
|
152
|
-
# `__array__` was implemented historically for compatibility, and removing it has
|
|
153
|
-
# caused issues for some libraries (see
|
|
154
|
-
# https://github.com/data-apis/array-api-strict/issues/67).
|
|
155
|
-
|
|
156
|
-
# Instead of `__array__` we now implement the buffer protocol.
|
|
157
|
-
# Note that it makes array-apis-strict requiring python>=3.12
|
|
158
154
|
def __buffer__(self, flags):
|
|
159
155
|
if self._device != CPU_DEVICE:
|
|
160
|
-
raise RuntimeError(
|
|
156
|
+
raise RuntimeError(
|
|
157
|
+
# NumPy swallows this exception and falls back to __array__.
|
|
158
|
+
f"Can't extract host buffer from array on the '{self._device}' device."
|
|
159
|
+
)
|
|
161
160
|
return self._array.__buffer__(flags)
|
|
162
161
|
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
# `__array__` is not part of the Array API. Ideally we want to support
|
|
163
|
+
# `xp.asarray(Array)` exclusively through the __buffer__ protocol; however this is
|
|
164
|
+
# only possible on Python >=3.12. Additionally, when __buffer__ raises (e.g. because
|
|
165
|
+
# the array is not on the CPU device, NumPy will try to fall back on __array__ but,
|
|
166
|
+
# if that doesn't exist, create a scalar numpy array of objects which contains the
|
|
167
|
+
# array_api_strict.Array. So we can't get rid of __array__ entirely.
|
|
168
|
+
def __array__(
|
|
169
|
+
self, dtype: None | np.dtype[Any] = None, copy: None | bool = None
|
|
170
|
+
) -> npt.NDArray[Any]:
|
|
171
|
+
if self._device != CPU_DEVICE:
|
|
172
|
+
# We arrive here from np.asarray() on Python >=3.12 when __buffer__ raises.
|
|
173
|
+
raise RuntimeError(
|
|
174
|
+
f"Can't convert array on the '{self._device}' device to a "
|
|
175
|
+
"NumPy array."
|
|
176
|
+
)
|
|
177
|
+
if sys.version_info >= (3, 12):
|
|
171
178
|
raise TypeError(
|
|
172
|
-
"
|
|
179
|
+
"The __array__ method is not supported by the Array API. "
|
|
180
|
+
"Please use the __buffer__ interface instead."
|
|
173
181
|
)
|
|
174
182
|
|
|
183
|
+
# copy keyword is new in 2.0
|
|
184
|
+
if np.__version__[0] < '2':
|
|
185
|
+
return np.asarray(self._array, dtype=dtype)
|
|
186
|
+
return np.asarray(self._array, dtype=dtype, copy=copy)
|
|
187
|
+
|
|
175
188
|
# These are various helper functions to make the array behavior match the
|
|
176
189
|
# spec in places where it either deviates from or is more strict than
|
|
177
190
|
# NumPy behavior
|
|
@@ -942,6 +955,15 @@ class Array:
|
|
|
942
955
|
self._validate_index(key, op="setitem")
|
|
943
956
|
# Indexing self._array with array_api_strict arrays can be erroneous
|
|
944
957
|
np_key = key._array if isinstance(key, Array) else key
|
|
958
|
+
|
|
959
|
+
# sanitize the value
|
|
960
|
+
other = value
|
|
961
|
+
if isinstance(value, (bool, int, float, complex)):
|
|
962
|
+
other = self._promote_scalar(value)
|
|
963
|
+
dt = _result_type(self.dtype, other.dtype)
|
|
964
|
+
if dt != self.dtype:
|
|
965
|
+
raise TypeError(f"mismatched dtypes: {self.dtype = } and {other.dtype = }")
|
|
966
|
+
|
|
945
967
|
self._array.__setitem__(np_key, asarray(value)._array)
|
|
946
968
|
|
|
947
969
|
def __sub__(self, other: Array | complex, /) -> Array:
|
|
@@ -1104,6 +1126,7 @@ class Array:
|
|
|
1104
1126
|
"""
|
|
1105
1127
|
Performs the operation __imod__.
|
|
1106
1128
|
"""
|
|
1129
|
+
self._check_type_device(other)
|
|
1107
1130
|
other = self._check_allowed_dtypes(other, "real numeric", "__imod__")
|
|
1108
1131
|
if other is NotImplemented:
|
|
1109
1132
|
return other
|
|
@@ -1126,6 +1149,7 @@ class Array:
|
|
|
1126
1149
|
"""
|
|
1127
1150
|
Performs the operation __imul__.
|
|
1128
1151
|
"""
|
|
1152
|
+
self._check_type_device(other)
|
|
1129
1153
|
other = self._check_allowed_dtypes(other, "numeric", "__imul__")
|
|
1130
1154
|
if other is NotImplemented:
|
|
1131
1155
|
return other
|
|
@@ -1148,6 +1172,7 @@ class Array:
|
|
|
1148
1172
|
"""
|
|
1149
1173
|
Performs the operation __ior__.
|
|
1150
1174
|
"""
|
|
1175
|
+
self._check_type_device(other)
|
|
1151
1176
|
other = self._check_allowed_dtypes(other, "integer or boolean", "__ior__")
|
|
1152
1177
|
if other is NotImplemented:
|
|
1153
1178
|
return other
|
|
@@ -1170,6 +1195,7 @@ class Array:
|
|
|
1170
1195
|
"""
|
|
1171
1196
|
Performs the operation __ipow__.
|
|
1172
1197
|
"""
|
|
1198
|
+
self._check_type_device(other)
|
|
1173
1199
|
other = self._check_allowed_dtypes(other, "numeric", "__ipow__")
|
|
1174
1200
|
if other is NotImplemented:
|
|
1175
1201
|
return other
|
|
@@ -1182,6 +1208,7 @@ class Array:
|
|
|
1182
1208
|
"""
|
|
1183
1209
|
from ._elementwise_functions import pow # type: ignore[attr-defined]
|
|
1184
1210
|
|
|
1211
|
+
self._check_type_device(other)
|
|
1185
1212
|
other = self._check_allowed_dtypes(other, "numeric", "__rpow__")
|
|
1186
1213
|
if other is NotImplemented:
|
|
1187
1214
|
return other
|
|
@@ -1193,6 +1220,7 @@ class Array:
|
|
|
1193
1220
|
"""
|
|
1194
1221
|
Performs the operation __irshift__.
|
|
1195
1222
|
"""
|
|
1223
|
+
self._check_type_device(other)
|
|
1196
1224
|
other = self._check_allowed_dtypes(other, "integer", "__irshift__")
|
|
1197
1225
|
if other is NotImplemented:
|
|
1198
1226
|
return other
|
|
@@ -1215,6 +1243,7 @@ class Array:
|
|
|
1215
1243
|
"""
|
|
1216
1244
|
Performs the operation __isub__.
|
|
1217
1245
|
"""
|
|
1246
|
+
self._check_type_device(other)
|
|
1218
1247
|
other = self._check_allowed_dtypes(other, "numeric", "__isub__")
|
|
1219
1248
|
if other is NotImplemented:
|
|
1220
1249
|
return other
|
|
@@ -1237,6 +1266,7 @@ class Array:
|
|
|
1237
1266
|
"""
|
|
1238
1267
|
Performs the operation __itruediv__.
|
|
1239
1268
|
"""
|
|
1269
|
+
self._check_type_device(other)
|
|
1240
1270
|
other = self._check_allowed_dtypes(other, "floating-point", "__itruediv__")
|
|
1241
1271
|
if other is NotImplemented:
|
|
1242
1272
|
return other
|
|
@@ -1259,6 +1289,7 @@ class Array:
|
|
|
1259
1289
|
"""
|
|
1260
1290
|
Performs the operation __ixor__.
|
|
1261
1291
|
"""
|
|
1292
|
+
self._check_type_device(other)
|
|
1262
1293
|
other = self._check_allowed_dtypes(other, "integer or boolean", "__ixor__")
|
|
1263
1294
|
if other is NotImplemented:
|
|
1264
1295
|
return other
|
|
@@ -240,8 +240,9 @@ def full(
|
|
|
240
240
|
_check_valid_dtype(dtype)
|
|
241
241
|
_check_device(device)
|
|
242
242
|
|
|
243
|
-
if isinstance(fill_value,
|
|
244
|
-
|
|
243
|
+
if not isinstance(fill_value, bool | int | float | complex):
|
|
244
|
+
msg = f"Expected Python scalar fill_value, got type {type(fill_value)}"
|
|
245
|
+
raise TypeError(msg)
|
|
245
246
|
res = np.full(shape, fill_value, dtype=_np_dtype(dtype))
|
|
246
247
|
if DType(res.dtype) not in _all_dtypes:
|
|
247
248
|
# This will happen if the fill value is not something that NumPy
|
|
@@ -270,6 +271,10 @@ def full_like(
|
|
|
270
271
|
if device is None:
|
|
271
272
|
device = x.device
|
|
272
273
|
|
|
274
|
+
if not isinstance(fill_value, bool | int | float | complex):
|
|
275
|
+
msg = f"Expected Python scalar fill_value, got type {type(fill_value)}"
|
|
276
|
+
raise TypeError(msg)
|
|
277
|
+
|
|
273
278
|
res = np.full_like(x._array, fill_value, dtype=_np_dtype(dtype))
|
|
274
279
|
if DType(res.dtype) not in _all_dtypes:
|
|
275
280
|
# This will happen if the fill value is not something that NumPy
|
|
@@ -304,7 +309,7 @@ def linspace(
|
|
|
304
309
|
)
|
|
305
310
|
|
|
306
311
|
|
|
307
|
-
def meshgrid(*arrays: Array, indexing: Literal["xy", "ij"] = "xy") ->
|
|
312
|
+
def meshgrid(*arrays: Array, indexing: Literal["xy", "ij"] = "xy") -> tuple[Array, ...]:
|
|
308
313
|
"""
|
|
309
314
|
Array API compatible wrapper for :py:func:`np.meshgrid <numpy.meshgrid>`.
|
|
310
315
|
|
|
@@ -327,10 +332,12 @@ def meshgrid(*arrays: Array, indexing: Literal["xy", "ij"] = "xy") -> list[Array
|
|
|
327
332
|
else:
|
|
328
333
|
device = None
|
|
329
334
|
|
|
330
|
-
|
|
335
|
+
typ = list if get_array_api_strict_flags()['api_version'] < '2025.12' else tuple
|
|
336
|
+
|
|
337
|
+
return typ(
|
|
331
338
|
Array._new(array, device=device)
|
|
332
339
|
for array in np.meshgrid(*[a._array for a in arrays], indexing=indexing)
|
|
333
|
-
|
|
340
|
+
)
|
|
334
341
|
|
|
335
342
|
|
|
336
343
|
def ones(
|
|
@@ -16,7 +16,7 @@ from ._dtypes import (
|
|
|
16
16
|
_signed_integer_dtypes,
|
|
17
17
|
_unsigned_integer_dtypes,
|
|
18
18
|
)
|
|
19
|
-
from ._flags import get_array_api_strict_flags
|
|
19
|
+
from ._flags import get_array_api_strict_flags, requires_api_version
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
# Note: astype is a function, not an array method as in NumPy.
|
|
@@ -49,7 +49,7 @@ def astype(
|
|
|
49
49
|
return Array._new(x._array.astype(dtype=dtype._np_dtype, copy=copy), device=device)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def broadcast_arrays(*arrays: Array) ->
|
|
52
|
+
def broadcast_arrays(*arrays: Array) -> tuple[Array, ...]:
|
|
53
53
|
"""
|
|
54
54
|
Array API compatible wrapper for :py:func:`np.broadcast_arrays <numpy.broadcast_arrays>`.
|
|
55
55
|
|
|
@@ -57,9 +57,21 @@ def broadcast_arrays(*arrays: Array) -> list[Array]:
|
|
|
57
57
|
"""
|
|
58
58
|
from ._array_object import Array
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
typ = list if get_array_api_strict_flags()['api_version'] < '2025.12' else tuple
|
|
61
|
+
|
|
62
|
+
return typ(
|
|
61
63
|
Array._new(array, device=arrays[0].device) for array in np.broadcast_arrays(*[a._array for a in arrays])
|
|
62
|
-
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@requires_api_version("2025.12")
|
|
68
|
+
def broadcast_shapes(*shapes: tuple[int, ...]) -> tuple[int, ...]:
|
|
69
|
+
"""
|
|
70
|
+
Array API compatible wrapper for :py:func:`np.broadcast_shapes <numpy.broadcast_shapes>`.
|
|
71
|
+
|
|
72
|
+
See its docstring for more information.
|
|
73
|
+
"""
|
|
74
|
+
return np.broadcast_shapes(*shapes)
|
|
63
75
|
|
|
64
76
|
|
|
65
77
|
def broadcast_to(x: Array, /, shape: tuple[int, ...]) -> Array:
|
|
@@ -257,7 +257,7 @@ def clip(
|
|
|
257
257
|
raise TypeError("Only real numeric dtypes are allowed in clip")
|
|
258
258
|
|
|
259
259
|
if min is max is None:
|
|
260
|
-
return x
|
|
260
|
+
return Array._new(x._array.copy(), device=x.device)
|
|
261
261
|
|
|
262
262
|
for argname, arg in ("min", min), ("max", max):
|
|
263
263
|
if isinstance(arg, Array):
|
|
@@ -278,8 +278,8 @@ def clip(
|
|
|
278
278
|
isinstance(arg, Array) and arg.dtype in _real_floating_dtypes)):
|
|
279
279
|
raise TypeError(f"{argname} must be integral when x is integral")
|
|
280
280
|
if (x.dtype in _real_floating_dtypes
|
|
281
|
-
and (isinstance(arg,
|
|
282
|
-
|
|
281
|
+
and (isinstance(arg, Array) and arg.dtype in _integer_dtypes)
|
|
282
|
+
):
|
|
283
283
|
raise TypeError(f"{arg} must be floating-point when x is floating-point")
|
|
284
284
|
|
|
285
285
|
# Normalize to make the below logic simpler
|
|
@@ -352,5 +352,7 @@ def sign(x: Array, /) -> Array:
|
|
|
352
352
|
raise TypeError("Only numeric dtypes are allowed in sign")
|
|
353
353
|
# Special treatment to work around non-compliant NumPy 1.x behaviour
|
|
354
354
|
if x.dtype in _complex_floating_dtypes:
|
|
355
|
-
|
|
355
|
+
_x = x._array
|
|
356
|
+
_result = _x / np.abs(np.where(_x != 0, _x, np.asarray(1.0, dtype=_x.dtype)))
|
|
357
|
+
return Array._new(_result, device=x.device)
|
|
356
358
|
return Array._new(np.sign(x._array), device=x.device)
|
|
@@ -30,11 +30,12 @@ supported_versions = (
|
|
|
30
30
|
"2022.12",
|
|
31
31
|
"2023.12",
|
|
32
32
|
"2024.12",
|
|
33
|
+
"2025.12",
|
|
33
34
|
)
|
|
34
35
|
|
|
35
|
-
draft_version = "
|
|
36
|
+
draft_version = "2026.12"
|
|
36
37
|
|
|
37
|
-
API_VERSION = default_version = "
|
|
38
|
+
API_VERSION = default_version = "2025.12"
|
|
38
39
|
|
|
39
40
|
BOOLEAN_INDEXING = True
|
|
40
41
|
|