array-api-strict 2.4.1__py3-none-any.whl → 2.5__py3-none-any.whl
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/__init__.py +4 -2
- array_api_strict/_array_object.py +4 -1
- array_api_strict/_creation_functions.py +12 -5
- array_api_strict/_data_type_functions.py +16 -4
- array_api_strict/_elementwise_functions.py +6 -4
- array_api_strict/_flags.py +3 -2
- array_api_strict/_info.py +5 -2
- array_api_strict/_linalg.py +62 -1
- array_api_strict/_manipulation_functions.py +1 -1
- array_api_strict/_searching_functions.py +8 -2
- array_api_strict/_set_functions.py +23 -1
- array_api_strict/_version.py +16 -3
- array_api_strict/tests/test_array_object.py +25 -9
- array_api_strict/tests/test_creation_functions.py +2 -0
- array_api_strict/tests/test_elementwise_functions.py +16 -4
- array_api_strict/tests/test_flags.py +11 -11
- {array_api_strict-2.4.1.dist-info → array_api_strict-2.5.dist-info}/METADATA +4 -1
- {array_api_strict-2.4.1.dist-info → array_api_strict-2.5.dist-info}/RECORD +21 -21
- {array_api_strict-2.4.1.dist-info → array_api_strict-2.5.dist-info}/LICENSE +0 -0
- {array_api_strict-2.4.1.dist-info → array_api_strict-2.5.dist-info}/WHEEL +0 -0
- {array_api_strict-2.4.1.dist-info → array_api_strict-2.5.dist-info}/top_level.txt +0 -0
array_api_strict/__init__.py
CHANGED
|
@@ -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
|
|
|
@@ -20,7 +20,7 @@ import sys
|
|
|
20
20
|
from collections.abc import Iterator
|
|
21
21
|
from enum import IntEnum
|
|
22
22
|
from types import EllipsisType, ModuleType
|
|
23
|
-
from typing import Any, Final, Literal, SupportsIndex
|
|
23
|
+
from typing import Any, Final, Literal, SupportsIndex, Callable
|
|
24
24
|
|
|
25
25
|
import numpy as np
|
|
26
26
|
import numpy.typing as npt
|
|
@@ -125,6 +125,9 @@ class Array:
|
|
|
125
125
|
raise TypeError(
|
|
126
126
|
"The array_api_strict Array object should not be instantiated directly. Use an array creation function, such as asarray(), instead."
|
|
127
127
|
)
|
|
128
|
+
|
|
129
|
+
def __reduce__(self) -> tuple[Callable, tuple[npt.NDArray[Any], Device]]:
|
|
130
|
+
return (self._new, (self._array, self._device))
|
|
128
131
|
|
|
129
132
|
# These functions are not required by the spec, but are implemented for
|
|
130
133
|
# the sake of usability.
|
|
@@ -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)
|
array_api_strict/_flags.py
CHANGED
|
@@ -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
|
|
array_api_strict/_info.py
CHANGED
|
@@ -130,5 +130,8 @@ class __array_namespace_info__:
|
|
|
130
130
|
raise ValueError(f"unsupported kind: {kind!r}")
|
|
131
131
|
|
|
132
132
|
@requires_api_version('2023.12')
|
|
133
|
-
def devices(self) ->
|
|
134
|
-
|
|
133
|
+
def devices(self) -> tuple[Device]:
|
|
134
|
+
if get_array_api_strict_flags()['api_version'] < '2025.12':
|
|
135
|
+
return list(ALL_DEVICES)
|
|
136
|
+
else:
|
|
137
|
+
return tuple(ALL_DEVICES)
|
array_api_strict/_linalg.py
CHANGED
|
@@ -9,7 +9,7 @@ from ._array_object import Array
|
|
|
9
9
|
from ._data_type_functions import finfo
|
|
10
10
|
from ._dtypes import DType, _floating_dtypes, _numeric_dtypes, complex64, complex128
|
|
11
11
|
from ._elementwise_functions import conj
|
|
12
|
-
from ._flags import get_array_api_strict_flags, requires_extension
|
|
12
|
+
from ._flags import get_array_api_strict_flags, requires_extension, requires_api_version
|
|
13
13
|
from ._manipulation_functions import reshape
|
|
14
14
|
from ._statistical_functions import _np_dtype_sumprod
|
|
15
15
|
|
|
@@ -23,6 +23,10 @@ class EighResult(NamedTuple):
|
|
|
23
23
|
eigenvalues: Array
|
|
24
24
|
eigenvectors: Array
|
|
25
25
|
|
|
26
|
+
class EigResult(NamedTuple):
|
|
27
|
+
eigenvalues: Array
|
|
28
|
+
eigenvectors: Array
|
|
29
|
+
|
|
26
30
|
class QRResult(NamedTuple):
|
|
27
31
|
Q: Array
|
|
28
32
|
R: Array
|
|
@@ -144,6 +148,63 @@ def eigvalsh(x: Array, /) -> Array:
|
|
|
144
148
|
|
|
145
149
|
return Array._new(np.linalg.eigvalsh(x._array), device=x.device)
|
|
146
150
|
|
|
151
|
+
@requires_extension('linalg')
|
|
152
|
+
@requires_api_version('2025.12')
|
|
153
|
+
def eigvals(x: Array, /) -> Array:
|
|
154
|
+
"""
|
|
155
|
+
Array API compatible wrapper for :py:func:`np.linalg.eigvals <numpy.linalg.eigvals>`.
|
|
156
|
+
|
|
157
|
+
See its docstring for more information.
|
|
158
|
+
"""
|
|
159
|
+
# Note: the restriction to floating-point dtypes only is different from
|
|
160
|
+
# np.linalg.eigvals.
|
|
161
|
+
if x.dtype not in _floating_dtypes:
|
|
162
|
+
raise TypeError('Only floating-point dtypes are allowed in eigvals')
|
|
163
|
+
|
|
164
|
+
res = np.linalg.eigvals(x._array)
|
|
165
|
+
|
|
166
|
+
# numpy return reals for real inputs
|
|
167
|
+
res_dtype = res.dtype
|
|
168
|
+
if res.dtype == np.float32:
|
|
169
|
+
res_dtype = np.complex64
|
|
170
|
+
elif res.dtype == np.float64:
|
|
171
|
+
res_dtype = np.complex128
|
|
172
|
+
|
|
173
|
+
if res_dtype != res.dtype:
|
|
174
|
+
res = res.astype(res_dtype)
|
|
175
|
+
|
|
176
|
+
return Array._new(res, device=x.device)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@requires_extension('linalg')
|
|
180
|
+
@requires_api_version('2025.12')
|
|
181
|
+
def eig(x: Array, /) -> EigResult:
|
|
182
|
+
"""
|
|
183
|
+
Array API compatible wrapper for :py:func:`np.linalg.eig <numpy.linalg.eig>`.
|
|
184
|
+
|
|
185
|
+
See its docstring for more information.
|
|
186
|
+
"""
|
|
187
|
+
# Note: the restriction to floating-point dtypes only is different from
|
|
188
|
+
# np.linalg.eig.
|
|
189
|
+
if x.dtype not in _floating_dtypes:
|
|
190
|
+
raise TypeError('Only floating-point dtypes are allowed in eig')
|
|
191
|
+
|
|
192
|
+
w, vr = np.linalg.eig(x._array)
|
|
193
|
+
|
|
194
|
+
# numpy return reals for real inputs
|
|
195
|
+
res_dtype = w.dtype
|
|
196
|
+
if w.dtype == np.float32:
|
|
197
|
+
res_dtype = np.complex64
|
|
198
|
+
elif w.dtype == np.float64:
|
|
199
|
+
res_dtype = np.complex128
|
|
200
|
+
|
|
201
|
+
if res_dtype != w.dtype:
|
|
202
|
+
w = w.astype(res_dtype)
|
|
203
|
+
vr = vr.astype(res_dtype)
|
|
204
|
+
|
|
205
|
+
return EigResult(Array._new(w, device=x.device), Array._new(vr, device=x.device))
|
|
206
|
+
|
|
207
|
+
|
|
147
208
|
@requires_extension('linalg')
|
|
148
209
|
def inv(x: Array, /) -> Array:
|
|
149
210
|
"""
|
|
@@ -5,7 +5,7 @@ import numpy as np
|
|
|
5
5
|
from ._array_object import Array
|
|
6
6
|
from ._dtypes import _real_numeric_dtypes, _result_type
|
|
7
7
|
from ._dtypes import bool as _bool
|
|
8
|
-
from ._flags import requires_api_version, requires_data_dependent_shapes
|
|
8
|
+
from ._flags import requires_api_version, requires_data_dependent_shapes, get_array_api_strict_flags
|
|
9
9
|
from ._helpers import _maybe_normalize_py_scalars
|
|
10
10
|
|
|
11
11
|
|
|
@@ -64,7 +64,7 @@ def count_nonzero(
|
|
|
64
64
|
@requires_api_version('2023.12')
|
|
65
65
|
def searchsorted(
|
|
66
66
|
x1: Array,
|
|
67
|
-
x2: Array,
|
|
67
|
+
x2: Array | int | float,
|
|
68
68
|
/,
|
|
69
69
|
*,
|
|
70
70
|
side: Literal["left", "right"] = "left",
|
|
@@ -75,6 +75,12 @@ def searchsorted(
|
|
|
75
75
|
|
|
76
76
|
See its docstring for more information.
|
|
77
77
|
"""
|
|
78
|
+
flags = get_array_api_strict_flags()
|
|
79
|
+
if flags["api_version"] >= "2025.12":
|
|
80
|
+
# scalar x2 support is new in 2025.12
|
|
81
|
+
if isinstance(x2, bool | int | float | complex):
|
|
82
|
+
x2 = x1._promote_scalar(x2)
|
|
83
|
+
|
|
78
84
|
if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
|
|
79
85
|
raise TypeError("Only real numeric dtypes are allowed in searchsorted")
|
|
80
86
|
|
|
@@ -3,7 +3,9 @@ from typing import NamedTuple
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
5
|
from ._array_object import Array
|
|
6
|
-
from ._flags import requires_data_dependent_shapes
|
|
6
|
+
from ._flags import requires_data_dependent_shapes, requires_api_version
|
|
7
|
+
from ._helpers import _maybe_normalize_py_scalars
|
|
8
|
+
from ._dtypes import _result_type
|
|
7
9
|
|
|
8
10
|
# Note: np.unique() is split into four functions in the array API:
|
|
9
11
|
# unique_all, unique_counts, unique_inverse, and unique_values (this is done
|
|
@@ -109,3 +111,23 @@ def unique_values(x: Array, /) -> Array:
|
|
|
109
111
|
equal_nan=False,
|
|
110
112
|
)
|
|
111
113
|
return Array._new(res, device=x.device)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@requires_api_version('2025.12')
|
|
117
|
+
def isin(x1: Array | int, x2: Array | int, /, *, invert: bool = False) -> Array:
|
|
118
|
+
"""
|
|
119
|
+
Array API compatible wrapper for :py:func:`np.isin <numpy.isin>`.
|
|
120
|
+
|
|
121
|
+
See its docstring for more information.
|
|
122
|
+
"""
|
|
123
|
+
# implementation here is from _elementwise_functions.py::_binary_ufunc_proto
|
|
124
|
+
x1, x2 = _maybe_normalize_py_scalars(x1, x2, "integer", "isin")
|
|
125
|
+
|
|
126
|
+
if x1.device != x2.device:
|
|
127
|
+
raise ValueError(
|
|
128
|
+
f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined."
|
|
129
|
+
)
|
|
130
|
+
# Call result type here just to raise on disallowed type combinations
|
|
131
|
+
_result_type(x1.dtype, x2.dtype)
|
|
132
|
+
# x1, x2 = Array._normalize_two_args(x1, x2) # no need to change 0D -> 1D here
|
|
133
|
+
return Array._new(np.isin(x1._array, x2._array), device=x1.device)
|
array_api_strict/_version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '2.
|
|
21
|
-
__version_tuple__ = version_tuple = (2,
|
|
31
|
+
__version__ = version = '2.5'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 5)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
import warnings
|
|
2
3
|
import operator
|
|
4
|
+
import pickle
|
|
3
5
|
from builtins import all as all_
|
|
4
6
|
|
|
5
|
-
from numpy.testing import assert_raises
|
|
7
|
+
from numpy.testing import assert_raises
|
|
6
8
|
import numpy as np
|
|
7
9
|
import pytest
|
|
8
10
|
|
|
@@ -269,10 +271,12 @@ def _check_op_array_scalar(dtypes, a, s, func, func_name, BIG_INT=BIG_INT):
|
|
|
269
271
|
|
|
270
272
|
else:
|
|
271
273
|
# Only test for no error
|
|
272
|
-
with
|
|
274
|
+
with warnings.catch_warnings():
|
|
273
275
|
# ignore warnings from pow(BIG_INT)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
+
warnings.filterwarnings(
|
|
277
|
+
"ignore", category=RuntimeWarning,
|
|
278
|
+
message="invalid value encountered in power"
|
|
279
|
+
)
|
|
276
280
|
func(s)
|
|
277
281
|
return True
|
|
278
282
|
|
|
@@ -666,10 +670,10 @@ def test_array_keys_use_private_array():
|
|
|
666
670
|
def test_array_namespace():
|
|
667
671
|
a = ones((3, 3))
|
|
668
672
|
assert a.__array_namespace__() == array_api_strict
|
|
669
|
-
assert array_api_strict.__array_api_version__ == "
|
|
673
|
+
assert array_api_strict.__array_api_version__ == "2025.12"
|
|
670
674
|
|
|
671
675
|
assert a.__array_namespace__(api_version=None) is array_api_strict
|
|
672
|
-
assert array_api_strict.__array_api_version__ == "
|
|
676
|
+
assert array_api_strict.__array_api_version__ == "2025.12"
|
|
673
677
|
|
|
674
678
|
assert a.__array_namespace__(api_version="2022.12") is array_api_strict
|
|
675
679
|
assert array_api_strict.__array_api_version__ == "2022.12"
|
|
@@ -682,12 +686,12 @@ def test_array_namespace():
|
|
|
682
686
|
assert array_api_strict.__array_api_version__ == "2021.12"
|
|
683
687
|
|
|
684
688
|
with pytest.warns(UserWarning):
|
|
685
|
-
assert a.__array_namespace__(api_version="
|
|
686
|
-
assert array_api_strict.__array_api_version__ == "
|
|
689
|
+
assert a.__array_namespace__(api_version="2026.12") is array_api_strict
|
|
690
|
+
assert array_api_strict.__array_api_version__ == "2026.12"
|
|
687
691
|
|
|
688
692
|
|
|
689
693
|
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2021.11"))
|
|
690
|
-
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="
|
|
694
|
+
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2027.12"))
|
|
691
695
|
|
|
692
696
|
def test_iter():
|
|
693
697
|
pytest.raises(TypeError, lambda: next(iter(asarray(3))))
|
|
@@ -744,3 +748,15 @@ def test_dlpack_2023_12(api_version):
|
|
|
744
748
|
a.__dlpack__(copy=False)
|
|
745
749
|
a.__dlpack__(copy=True)
|
|
746
750
|
a.__dlpack__(copy=None)
|
|
751
|
+
|
|
752
|
+
def test_pickle():
|
|
753
|
+
"""Check that arrays are pickleable (despite raising on `__new__`)"""
|
|
754
|
+
a = ones(2)
|
|
755
|
+
min_supported_protocol = 2
|
|
756
|
+
for protocol in range(min_supported_protocol, pickle.HIGHEST_PROTOCOL + 1):
|
|
757
|
+
bytes = pickle.dumps(a, protocol=protocol)
|
|
758
|
+
a_from_pickle = pickle.loads(bytes)
|
|
759
|
+
assert a_from_pickle.device == a.device
|
|
760
|
+
assert a_from_pickle.dtype == a.dtype
|
|
761
|
+
assert a_from_pickle.shape == a.shape
|
|
762
|
+
assert all(a_from_pickle == a)
|
|
@@ -161,6 +161,7 @@ def test_full_errors():
|
|
|
161
161
|
assert_raises(ValueError, lambda: full((1,), 0, device="gpu"))
|
|
162
162
|
assert_raises(ValueError, lambda: full((1,), 0, dtype=int))
|
|
163
163
|
assert_raises(ValueError, lambda: full((1,), 0, dtype="i"))
|
|
164
|
+
assert_raises(TypeError, lambda: full((1,), asarray(0)))
|
|
164
165
|
|
|
165
166
|
|
|
166
167
|
def test_full_like_errors():
|
|
@@ -169,6 +170,7 @@ def test_full_like_errors():
|
|
|
169
170
|
assert_raises(ValueError, lambda: full_like(asarray(1), 0, device="gpu"))
|
|
170
171
|
assert_raises(ValueError, lambda: full_like(asarray(1), 0, dtype=int))
|
|
171
172
|
assert_raises(ValueError, lambda: full_like(asarray(1), 0, dtype="i"))
|
|
173
|
+
assert_raises(TypeError, lambda: full(asarray(1), asarray(0)))
|
|
172
174
|
|
|
173
175
|
|
|
174
176
|
def test_linspace_errors():
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from inspect import signature, getmodule
|
|
2
3
|
|
|
3
4
|
import numpy as np
|
|
4
5
|
import pytest
|
|
5
|
-
from numpy.testing import suppress_warnings
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
from .. import asarray, _elementwise_functions
|
|
@@ -300,12 +300,24 @@ def test_scalars():
|
|
|
300
300
|
if allowed:
|
|
301
301
|
conv_scalar = a._promote_scalar(s)
|
|
302
302
|
|
|
303
|
-
with
|
|
303
|
+
with warnings.catch_warnings():
|
|
304
304
|
# ignore warnings from pow(BIG_INT)
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
warnings.filterwarnings(
|
|
306
|
+
"ignore", category=RuntimeWarning,
|
|
307
|
+
message="invalid value encountered in power"
|
|
308
|
+
)
|
|
309
|
+
|
|
307
310
|
assert func(s, a) == func(conv_scalar, a)
|
|
308
311
|
assert func(a, s) == func(a, conv_scalar)
|
|
309
312
|
|
|
310
313
|
with pytest.raises(TypeError):
|
|
311
314
|
func(s, s)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def test_clip_none():
|
|
318
|
+
# regression test: clip(x) is a copy of x, not a view
|
|
319
|
+
x = asarray([1, 2, 3])
|
|
320
|
+
y = array_api_strict.clip(x)
|
|
321
|
+
|
|
322
|
+
y[1] = 42
|
|
323
|
+
assert x[1] == 2
|
|
@@ -19,7 +19,7 @@ import pytest
|
|
|
19
19
|
def test_flag_defaults():
|
|
20
20
|
flags = get_array_api_strict_flags()
|
|
21
21
|
assert flags == {
|
|
22
|
-
'api_version': '
|
|
22
|
+
'api_version': '2025.12',
|
|
23
23
|
'boolean_indexing': True,
|
|
24
24
|
'data_dependent_shapes': True,
|
|
25
25
|
'enabled_extensions': ('linalg', 'fft'),
|
|
@@ -36,7 +36,7 @@ def test_reset_flags():
|
|
|
36
36
|
reset_array_api_strict_flags()
|
|
37
37
|
flags = get_array_api_strict_flags()
|
|
38
38
|
assert flags == {
|
|
39
|
-
'api_version': '
|
|
39
|
+
'api_version': '2025.12',
|
|
40
40
|
'boolean_indexing': True,
|
|
41
41
|
'data_dependent_shapes': True,
|
|
42
42
|
'enabled_extensions': ('linalg', 'fft'),
|
|
@@ -47,7 +47,7 @@ def test_setting_flags():
|
|
|
47
47
|
set_array_api_strict_flags(data_dependent_shapes=False)
|
|
48
48
|
flags = get_array_api_strict_flags()
|
|
49
49
|
assert flags == {
|
|
50
|
-
'api_version': '
|
|
50
|
+
'api_version': '2025.12',
|
|
51
51
|
'boolean_indexing': True,
|
|
52
52
|
'data_dependent_shapes': False,
|
|
53
53
|
'enabled_extensions': ('linalg', 'fft'),
|
|
@@ -55,7 +55,7 @@ def test_setting_flags():
|
|
|
55
55
|
set_array_api_strict_flags(enabled_extensions=('fft',))
|
|
56
56
|
flags = get_array_api_strict_flags()
|
|
57
57
|
assert flags == {
|
|
58
|
-
'api_version': '
|
|
58
|
+
'api_version': '2025.12',
|
|
59
59
|
'boolean_indexing': True,
|
|
60
60
|
'data_dependent_shapes': False,
|
|
61
61
|
'enabled_extensions': ('fft',),
|
|
@@ -109,15 +109,15 @@ def test_flags_api_version_2024_12():
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def test_flags_api_version_2025_12():
|
|
112
|
-
# Make sure setting the version to
|
|
112
|
+
# Make sure setting the version to 2026.12 issues a warning.
|
|
113
113
|
with pytest.warns(UserWarning) as record:
|
|
114
|
-
set_array_api_strict_flags(api_version='
|
|
114
|
+
set_array_api_strict_flags(api_version='2026.12')
|
|
115
115
|
assert len(record) == 1
|
|
116
|
-
assert '
|
|
116
|
+
assert '2026.12' in str(record[0].message)
|
|
117
117
|
assert 'draft' in str(record[0].message)
|
|
118
118
|
flags = get_array_api_strict_flags()
|
|
119
119
|
assert flags == {
|
|
120
|
-
'api_version': '
|
|
120
|
+
'api_version': '2026.12',
|
|
121
121
|
'boolean_indexing': True,
|
|
122
122
|
'data_dependent_shapes': True,
|
|
123
123
|
'enabled_extensions': ('linalg', 'fft'),
|
|
@@ -136,7 +136,7 @@ def test_setting_flags_invalid():
|
|
|
136
136
|
|
|
137
137
|
def test_api_version():
|
|
138
138
|
# Test defaults
|
|
139
|
-
assert xp.__array_api_version__ == '
|
|
139
|
+
assert xp.__array_api_version__ == '2025.12'
|
|
140
140
|
|
|
141
141
|
# Test setting the version
|
|
142
142
|
set_array_api_strict_flags(api_version='2023.12')
|
|
@@ -444,9 +444,9 @@ def test_environment_variables():
|
|
|
444
444
|
# ARRAY_API_STRICT_API_VERSION
|
|
445
445
|
('''\
|
|
446
446
|
import array_api_strict as xp
|
|
447
|
-
assert xp.__array_api_version__ == '
|
|
447
|
+
assert xp.__array_api_version__ == '2025.12'
|
|
448
448
|
|
|
449
|
-
assert xp.get_array_api_strict_flags()['api_version'] == '
|
|
449
|
+
assert xp.get_array_api_strict_flags()['api_version'] == '2025.12'
|
|
450
450
|
|
|
451
451
|
''', {}),
|
|
452
452
|
*[
|
|
@@ -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
|
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
array_api_strict/__init__.py,sha256=
|
|
2
|
-
array_api_strict/_array_object.py,sha256=
|
|
1
|
+
array_api_strict/__init__.py,sha256=kexXRJ7WHgMTeMi80H6XiObC3ePtUEr5gf92dnwyPGE,7173
|
|
2
|
+
array_api_strict/_array_object.py,sha256=m5197OW2aW778dGDMjQI4Zxaw5BfIqXWQ6sJK_DpgaA,54393
|
|
3
3
|
array_api_strict/_constants.py,sha256=ilkAGjIceZxT4zPywIoWbl3Xv8k19UOI4SSF6EPegpg,93
|
|
4
|
-
array_api_strict/_creation_functions.py,sha256=
|
|
5
|
-
array_api_strict/_data_type_functions.py,sha256=
|
|
4
|
+
array_api_strict/_creation_functions.py,sha256=TXookrcG1zeUBMvgFdbiwXxZJ1aMvViSef24tqVo53s,12658
|
|
5
|
+
array_api_strict/_data_type_functions.py,sha256=5OPnsIj4QafrSlnizUZcO4DHO5u0ap9OyDNovV4qrns,8765
|
|
6
6
|
array_api_strict/_dtypes.py,sha256=PNSd4LpGdnRiEGoB2uqxi93d0dmtiyFp_awUzUcdHJE,6597
|
|
7
|
-
array_api_strict/_elementwise_functions.py,sha256=
|
|
7
|
+
array_api_strict/_elementwise_functions.py,sha256=D3jOalyR5-kDSzeGTZLKnGPVwjKBuPihkwn23YSxcUc,13198
|
|
8
8
|
array_api_strict/_fft.py,sha256=DVw7KK4Xvyf3_0rJuWdskggGRCSxS4OrguYNVBf9fH0,10189
|
|
9
|
-
array_api_strict/_flags.py,sha256=
|
|
9
|
+
array_api_strict/_flags.py,sha256=JaaGahMa-yQjz9fq2E_cFQvhh5B5rVJKms9pMcwdKAg,14758
|
|
10
10
|
array_api_strict/_helpers.py,sha256=St8M41s5pdhdPdn1-BcdZCrNtRID4X9z5F28fBD3GNg,1915
|
|
11
11
|
array_api_strict/_indexing_functions.py,sha256=BHPtoyRUIoEMe28MkwUrHRSz5X71i8w_WkTuWQljrpI,1398
|
|
12
|
-
array_api_strict/_info.py,sha256=
|
|
13
|
-
array_api_strict/_linalg.py,sha256=
|
|
12
|
+
array_api_strict/_info.py,sha256=nGLPkobKqDuLlLD4yOxG4y3JVO98o9UNEImXu6YeKH8,4532
|
|
13
|
+
array_api_strict/_linalg.py,sha256=HQjpkVPB0R59mOQBR4cqlZTUKOQTEjGEXbkwk3KNa2Y,21495
|
|
14
14
|
array_api_strict/_linear_algebra_functions.py,sha256=j8fSBharI31ugZHsUvm74Nv3SHxRrxqtmouK3AOH038,3800
|
|
15
|
-
array_api_strict/_manipulation_functions.py,sha256=
|
|
16
|
-
array_api_strict/_searching_functions.py,sha256=
|
|
17
|
-
array_api_strict/_set_functions.py,sha256=
|
|
15
|
+
array_api_strict/_manipulation_functions.py,sha256=KR0O7bMulglaX0DoqEWpiNK3V25D12mFdsqeq-vm8mg,6935
|
|
16
|
+
array_api_strict/_searching_functions.py,sha256=X7pT_kuGBpJltpo4MvVYiZdnKr7jgnH1DNtHiHTKdgw,4263
|
|
17
|
+
array_api_strict/_set_functions.py,sha256=yTKA2OqueeKwk8tp_XcpcsWliL02kgzT3NBzot5zuQ8,4196
|
|
18
18
|
array_api_strict/_sorting_functions.py,sha256=kw_ns3NajcA8ekpHikNhZxvVePXa3gjdZ7oTwFnBOmk,2074
|
|
19
19
|
array_api_strict/_statistical_functions.py,sha256=XR9PoZmxJWTsAbzYj05ytDn2D2YDf2YTzWNApdmJBIM,5642
|
|
20
20
|
array_api_strict/_typing.py,sha256=FVM2m6ZTZYDnznCo0SlMRpcXxGR49y6k4ejNEiuGUtc,1486
|
|
21
21
|
array_api_strict/_utility_functions.py,sha256=L7FJM-RT90gqkAqvMEfQ6FkzurTziHByROk_5R8a5fY,1938
|
|
22
|
-
array_api_strict/_version.py,sha256=
|
|
22
|
+
array_api_strict/_version.py,sha256=hJiFMfUPM_IAKDdGwMOVrwsdi46DfhTA5ZGiPklON8o,699
|
|
23
23
|
array_api_strict/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
array_api_strict/tests/__init__.py,sha256=t_2GZ3lKcsu4ec4GMKPUDYaeMUJyDquBlQAcPgj7kFE,282
|
|
25
25
|
array_api_strict/tests/conftest.py,sha256=-wIDryl2MdRLdSonU1G1xWssNq2TFKiWuHquNasXYA8,468
|
|
26
|
-
array_api_strict/tests/test_array_object.py,sha256=
|
|
27
|
-
array_api_strict/tests/test_creation_functions.py,sha256=
|
|
26
|
+
array_api_strict/tests/test_array_object.py,sha256=PZj2Ekw6sY1pbNBrjs2Ll3COkGRVXNsROxirpHfXHJ4,29186
|
|
27
|
+
array_api_strict/tests/test_creation_functions.py,sha256=KeBxgG65ZnKBwclNFZBjyoSwov3j-E3f9iMnXfUsmA8,8638
|
|
28
28
|
array_api_strict/tests/test_data_type_functions.py,sha256=6V7YeJavgsBmKtR1gvY1GTTlKzGyzPAHki1WtKFeVdU,4098
|
|
29
29
|
array_api_strict/tests/test_device_support.py,sha256=zpfhHxeRREoXfp0qZTlilm2ZceBc71uCKea1GMVe-ZU,855
|
|
30
|
-
array_api_strict/tests/test_elementwise_functions.py,sha256=
|
|
31
|
-
array_api_strict/tests/test_flags.py,sha256=
|
|
30
|
+
array_api_strict/tests/test_elementwise_functions.py,sha256=ZZOfPaCNIug026zv9IdhV2164jZZkRSwmteAnefFBGw,11396
|
|
31
|
+
array_api_strict/tests/test_flags.py,sha256=g7Tajftvmc2ih0a6U57FxcpmleEiDoMgCvzUt2S7MF4,18982
|
|
32
32
|
array_api_strict/tests/test_indexing_functions.py,sha256=C23FnuowVDC1OBuDH06pvsd61qM2dTpTwzw6UgC4BoY,1281
|
|
33
33
|
array_api_strict/tests/test_linalg.py,sha256=CJ4JnCkWyysMUAih3PI-ZZeOH-X39H0p-RKBoEwk6Jw,5675
|
|
34
34
|
array_api_strict/tests/test_manipulation_functions.py,sha256=Yc92IvA3FaTZueqAUOFMkx3MH4PXCHDof7ckrJxudQs,1078
|
|
@@ -37,8 +37,8 @@ array_api_strict/tests/test_set_functions.py,sha256=ikzab1j3SXxGf0OqwHrOAM13HwQe
|
|
|
37
37
|
array_api_strict/tests/test_sorting_functions.py,sha256=1xvQBKts5KTKYc-puMITX9iR_KTbzzVB8fY-SObad_Y,899
|
|
38
38
|
array_api_strict/tests/test_statistical_functions.py,sha256=0ihnw4W9vOqU6RMBOUw29Fg-xumXpfz0h05v0E0RsMQ,1814
|
|
39
39
|
array_api_strict/tests/test_validation.py,sha256=VDci4SgcAhxzSFVnFYBvJWXEsWRxHARnq9TwTfH02xg,635
|
|
40
|
-
array_api_strict-2.
|
|
41
|
-
array_api_strict-2.
|
|
42
|
-
array_api_strict-2.
|
|
43
|
-
array_api_strict-2.
|
|
44
|
-
array_api_strict-2.
|
|
40
|
+
array_api_strict-2.5.dist-info/LICENSE,sha256=djDm4UfHAJmycwFUNyUmrTdRkrFF9Ac8uqIlbxH7j5Y,1585
|
|
41
|
+
array_api_strict-2.5.dist-info/METADATA,sha256=0sP5kLahxH406PSNEXzGLED-PAWJEWZ9QV1EUg6asr4,3613
|
|
42
|
+
array_api_strict-2.5.dist-info/WHEEL,sha256=5Mi1sN9lKoFv_gxcPtisEVrJZihrm_beibeg5R6xb4I,91
|
|
43
|
+
array_api_strict-2.5.dist-info/top_level.txt,sha256=M4cE8VLgRHp_d9TPkbk7_I4JriELFdEJz-NKJJqAkAE,17
|
|
44
|
+
array_api_strict-2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|