array-api-strict 2.1.2__tar.gz → 2.2__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.1.2 → array_api_strict-2.2}/PKG-INFO +4 -5
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/__init__.py +8 -10
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_array_object.py +44 -17
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_creation_functions.py +23 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_elementwise_functions.py +25 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_flags.py +8 -3
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_indexing_functions.py +12 -0
- array_api_strict-2.2/array_api_strict/_info.py +139 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_typing.py +4 -3
- array_api_strict-2.2/array_api_strict/_utility_functions.py +69 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_version.py +3 -3
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_array_object.py +60 -17
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_elementwise_functions.py +8 -2
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_flags.py +53 -7
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict.egg-info/PKG-INFO +4 -5
- array_api_strict-2.2/array_api_strict.egg-info/requires.txt +1 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/setup.py +3 -4
- array_api_strict-2.1.2/array_api_strict/_info.py +0 -132
- array_api_strict-2.1.2/array_api_strict/_utility_functions.py +0 -39
- array_api_strict-2.1.2/array_api_strict.egg-info/requires.txt +0 -1
- {array_api_strict-2.1.2 → array_api_strict-2.2}/LICENSE +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/README.md +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_constants.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_data_type_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_dtypes.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_fft.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_linalg.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_linear_algebra_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_manipulation_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_searching_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_set_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_sorting_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_statistical_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/__init__.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/conftest.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_creation_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_data_type_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_device_support.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_indexing_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_linalg.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_manipulation_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_set_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_sorting_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_statistical_functions.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_validation.py +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict.egg-info/SOURCES.txt +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict.egg-info/dependency_links.txt +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict.egg-info/top_level.txt +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/setup.cfg +0 -0
- {array_api_strict-2.1.2 → array_api_strict-2.2}/versioneer.py +0 -0
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: array_api_strict
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2
|
|
4
4
|
Summary: A strict, minimal implementation of the Python array API standard.
|
|
5
5
|
Home-page: https://data-apis.org/array-api-strict/
|
|
6
6
|
Author: Consortium for Python Data API Standards
|
|
7
7
|
License: MIT
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
13
|
Classifier: License :: OSI Approved :: BSD License
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.9
|
|
17
16
|
Description-Content-Type: text/markdown
|
|
18
17
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: numpy
|
|
18
|
+
Requires-Dist: numpy
|
|
20
19
|
|
|
21
20
|
# array-api-strict
|
|
22
21
|
|
|
@@ -16,12 +16,6 @@ consuming libraries to test their array API usage.
|
|
|
16
16
|
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
import numpy as np
|
|
20
|
-
from numpy.lib import NumpyVersion
|
|
21
|
-
|
|
22
|
-
if NumpyVersion(np.__version__) < NumpyVersion('2.1.0'):
|
|
23
|
-
raise ImportError("array-api-strict requires NumPy >= 2.1.0")
|
|
24
|
-
|
|
25
19
|
__all__ = []
|
|
26
20
|
|
|
27
21
|
# Warning: __array_api_version__ could change globally with
|
|
@@ -178,10 +172,12 @@ from ._elementwise_functions import (
|
|
|
178
172
|
minimum,
|
|
179
173
|
multiply,
|
|
180
174
|
negative,
|
|
175
|
+
nextafter,
|
|
181
176
|
not_equal,
|
|
182
177
|
positive,
|
|
183
178
|
pow,
|
|
184
179
|
real,
|
|
180
|
+
reciprocal,
|
|
185
181
|
remainder,
|
|
186
182
|
round,
|
|
187
183
|
sign,
|
|
@@ -246,10 +242,12 @@ __all__ += [
|
|
|
246
242
|
"minimum",
|
|
247
243
|
"multiply",
|
|
248
244
|
"negative",
|
|
245
|
+
"nextafter",
|
|
249
246
|
"not_equal",
|
|
250
247
|
"positive",
|
|
251
248
|
"pow",
|
|
252
249
|
"real",
|
|
250
|
+
"reciprocal",
|
|
253
251
|
"remainder",
|
|
254
252
|
"round",
|
|
255
253
|
"sign",
|
|
@@ -264,9 +262,9 @@ __all__ += [
|
|
|
264
262
|
"trunc",
|
|
265
263
|
]
|
|
266
264
|
|
|
267
|
-
from ._indexing_functions import take
|
|
265
|
+
from ._indexing_functions import take, take_along_axis
|
|
268
266
|
|
|
269
|
-
__all__ += ["take"]
|
|
267
|
+
__all__ += ["take", "take_along_axis"]
|
|
270
268
|
|
|
271
269
|
from ._info import __array_namespace_info__
|
|
272
270
|
|
|
@@ -311,9 +309,9 @@ from ._statistical_functions import cumulative_sum, max, mean, min, prod, std, s
|
|
|
311
309
|
|
|
312
310
|
__all__ += ["cumulative_sum", "max", "mean", "min", "prod", "std", "sum", "var"]
|
|
313
311
|
|
|
314
|
-
from ._utility_functions import all, any
|
|
312
|
+
from ._utility_functions import all, any, diff
|
|
315
313
|
|
|
316
|
-
__all__ += ["all", "any"]
|
|
314
|
+
__all__ += ["all", "any", "diff"]
|
|
317
315
|
|
|
318
316
|
from ._array_object import Device
|
|
319
317
|
__all__ += ["Device"]
|
|
@@ -66,7 +66,9 @@ ALL_DEVICES = (CPU_DEVICE, Device("device1"), Device("device2"))
|
|
|
66
66
|
|
|
67
67
|
_default = object()
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
# See https://github.com/data-apis/array-api-strict/issues/67 and the comment
|
|
70
|
+
# on __array__ below.
|
|
71
|
+
_allow_array = True
|
|
70
72
|
|
|
71
73
|
class Array:
|
|
72
74
|
"""
|
|
@@ -147,22 +149,37 @@ class Array:
|
|
|
147
149
|
mid = np.array2string(self._array, separator=', ', prefix=prefix, suffix=suffix)
|
|
148
150
|
return prefix + mid + suffix
|
|
149
151
|
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
# used to do. But this isn't actually supported by the standard, so it can
|
|
152
|
+
# In the future, _allow_array will be set to False, which will disallow
|
|
153
|
+
# __array__. This means calling `np.func()` on an array_api_strict array
|
|
154
|
+
# will give an error. If we don't explicitly disallow it, NumPy defaults
|
|
155
|
+
# to creating an object dtype array, which would lead to confusing error
|
|
156
|
+
# messages at best and surprising bugs at worst. The reason for doing this
|
|
157
|
+
# is that __array__ is not actually supported by the standard, so it can
|
|
157
158
|
# lead to code assuming np.asarray(other_array) would always work in the
|
|
158
159
|
# standard.
|
|
160
|
+
#
|
|
161
|
+
# This was implemented historically for compatibility, and removing it has
|
|
162
|
+
# caused issues for some libraries (see
|
|
163
|
+
# https://github.com/data-apis/array-api-strict/issues/67).
|
|
159
164
|
def __array__(self, dtype: None | np.dtype[Any] = None, copy: None | bool = None) -> npt.NDArray[Any]:
|
|
160
165
|
# We have to allow this to be internally enabled as there's no other
|
|
161
166
|
# easy way to parse a list of Array objects in asarray().
|
|
162
167
|
if _allow_array:
|
|
163
168
|
if self._device != CPU_DEVICE:
|
|
164
169
|
raise RuntimeError(f"Can not convert array on the '{self._device}' device to a Numpy array.")
|
|
165
|
-
|
|
170
|
+
# copy keyword is new in 2.0.0; for older versions don't use it
|
|
171
|
+
# retry without that keyword.
|
|
172
|
+
if np.__version__[0] < '2':
|
|
173
|
+
return np.asarray(self._array, dtype=dtype)
|
|
174
|
+
elif np.__version__.startswith('2.0.0-dev0'):
|
|
175
|
+
# Handle dev version for which we can't know based on version
|
|
176
|
+
# number whether or not the copy keyword is supported.
|
|
177
|
+
try:
|
|
178
|
+
return np.asarray(self._array, dtype=dtype, copy=copy)
|
|
179
|
+
except TypeError:
|
|
180
|
+
return np.asarray(self._array, dtype=dtype)
|
|
181
|
+
else:
|
|
182
|
+
return np.asarray(self._array, dtype=dtype, copy=copy)
|
|
166
183
|
raise ValueError("Conversion from an array_api_strict array to a NumPy ndarray is not supported")
|
|
167
184
|
|
|
168
185
|
# These are various helper functions to make the array behavior match the
|
|
@@ -574,14 +591,24 @@ class Array:
|
|
|
574
591
|
if copy is not _default:
|
|
575
592
|
raise ValueError("The copy argument to __dlpack__ requires at least version 2023.12 of the array API")
|
|
576
593
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
594
|
+
if np.lib.NumpyVersion(np.__version__) < '2.1.0':
|
|
595
|
+
if max_version not in [_default, None]:
|
|
596
|
+
raise NotImplementedError("The max_version argument to __dlpack__ is not yet implemented")
|
|
597
|
+
if dl_device not in [_default, None]:
|
|
598
|
+
raise NotImplementedError("The device argument to __dlpack__ is not yet implemented")
|
|
599
|
+
if copy not in [_default, None]:
|
|
600
|
+
raise NotImplementedError("The copy argument to __dlpack__ is not yet implemented")
|
|
601
|
+
|
|
602
|
+
return self._array.__dlpack__(stream=stream)
|
|
603
|
+
else:
|
|
604
|
+
kwargs = {'stream': stream}
|
|
605
|
+
if max_version is not _default:
|
|
606
|
+
kwargs['max_version'] = max_version
|
|
607
|
+
if dl_device is not _default:
|
|
608
|
+
kwargs['dl_device'] = dl_device
|
|
609
|
+
if copy is not _default:
|
|
610
|
+
kwargs['copy'] = copy
|
|
611
|
+
return self._array.__dlpack__(**kwargs)
|
|
585
612
|
|
|
586
613
|
def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]:
|
|
587
614
|
"""
|
|
@@ -83,6 +83,29 @@ def asarray(
|
|
|
83
83
|
if isinstance(obj, Array) and device is None:
|
|
84
84
|
device = obj.device
|
|
85
85
|
|
|
86
|
+
if np.lib.NumpyVersion(np.__version__) < '2.0.0':
|
|
87
|
+
if copy is False:
|
|
88
|
+
# Note: copy=False is not yet implemented in np.asarray for
|
|
89
|
+
# NumPy 1
|
|
90
|
+
|
|
91
|
+
# Work around it by creating the new array and seeing if NumPy
|
|
92
|
+
# copies it.
|
|
93
|
+
if isinstance(obj, Array):
|
|
94
|
+
new_array = np.array(obj._array, copy=copy, dtype=_np_dtype)
|
|
95
|
+
if new_array is not obj._array:
|
|
96
|
+
raise ValueError("Unable to avoid copy while creating an array from given array.")
|
|
97
|
+
return Array._new(new_array, device=device)
|
|
98
|
+
elif _supports_buffer_protocol(obj):
|
|
99
|
+
# Buffer protocol will always support no-copy
|
|
100
|
+
return Array._new(np.array(obj, copy=copy, dtype=_np_dtype), device=device)
|
|
101
|
+
else:
|
|
102
|
+
# No-copy is unsupported for Python built-in types.
|
|
103
|
+
raise ValueError("Unable to avoid copy while creating an array from given object.")
|
|
104
|
+
|
|
105
|
+
if copy is None:
|
|
106
|
+
# NumPy 1 treats copy=False the same as the standard copy=None
|
|
107
|
+
copy = False
|
|
108
|
+
|
|
86
109
|
if isinstance(obj, Array):
|
|
87
110
|
return Array._new(np.array(obj._array, copy=copy, dtype=_np_dtype), device=device)
|
|
88
111
|
if dtype is None and isinstance(obj, int) and (obj > 2 ** 64 or obj < -(2 ** 63)):
|
|
@@ -805,6 +805,20 @@ def negative(x: Array, /) -> Array:
|
|
|
805
805
|
return Array._new(np.negative(x._array), device=x.device)
|
|
806
806
|
|
|
807
807
|
|
|
808
|
+
@requires_api_version('2024.12')
|
|
809
|
+
def nextafter(x1: Array, x2: Array, /) -> Array:
|
|
810
|
+
"""
|
|
811
|
+
Array API compatible wrapper for :py:func:`np.nextafter <numpy.nextafter>`.
|
|
812
|
+
|
|
813
|
+
See its docstring for more information.
|
|
814
|
+
"""
|
|
815
|
+
if x1.device != x2.device:
|
|
816
|
+
raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
|
|
817
|
+
if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
|
|
818
|
+
raise TypeError("Only real floating-point dtypes are allowed in nextafter")
|
|
819
|
+
x1, x2 = Array._normalize_two_args(x1, x2)
|
|
820
|
+
return Array._new(np.nextafter(x1._array, x2._array), device=x1.device)
|
|
821
|
+
|
|
808
822
|
def not_equal(x1: Array, x2: Array, /) -> Array:
|
|
809
823
|
"""
|
|
810
824
|
Array API compatible wrapper for :py:func:`np.not_equal <numpy.not_equal>`.
|
|
@@ -858,6 +872,17 @@ def real(x: Array, /) -> Array:
|
|
|
858
872
|
return Array._new(np.real(x._array), device=x.device)
|
|
859
873
|
|
|
860
874
|
|
|
875
|
+
@requires_api_version('2024.12')
|
|
876
|
+
def reciprocal(x: Array, /) -> Array:
|
|
877
|
+
"""
|
|
878
|
+
Array API compatible wrapper for :py:func:`np.reciprocal <numpy.reciprocal>`.
|
|
879
|
+
|
|
880
|
+
See its docstring for more information.
|
|
881
|
+
"""
|
|
882
|
+
if x.dtype not in _floating_dtypes:
|
|
883
|
+
raise TypeError("Only floating-point dtypes are allowed in reciprocal")
|
|
884
|
+
return Array._new(np.reciprocal(x._array), device=x.device)
|
|
885
|
+
|
|
861
886
|
def remainder(x1: Array, x2: Array, /) -> Array:
|
|
862
887
|
"""
|
|
863
888
|
Array API compatible wrapper for :py:func:`np.remainder <numpy.remainder>`.
|
|
@@ -24,6 +24,8 @@ supported_versions = (
|
|
|
24
24
|
"2023.12",
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
+
draft_version = "2024.12"
|
|
28
|
+
|
|
27
29
|
API_VERSION = default_version = "2023.12"
|
|
28
30
|
|
|
29
31
|
BOOLEAN_INDEXING = True
|
|
@@ -70,8 +72,8 @@ def set_array_api_strict_flags(
|
|
|
70
72
|
----------
|
|
71
73
|
api_version : str, optional
|
|
72
74
|
The version of the standard to use. Supported versions are:
|
|
73
|
-
``{supported_versions}
|
|
74
|
-
``{default_version!r}``.
|
|
75
|
+
``{supported_versions}``, plus the draft version ``{draft_version}``.
|
|
76
|
+
The default version number is ``{default_version!r}``.
|
|
75
77
|
|
|
76
78
|
Note that 2021.12 is supported, but currently gives the same thing as
|
|
77
79
|
2022.12 (except that the fft extension will be disabled).
|
|
@@ -134,10 +136,12 @@ def set_array_api_strict_flags(
|
|
|
134
136
|
global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS
|
|
135
137
|
|
|
136
138
|
if api_version is not None:
|
|
137
|
-
if api_version not in supported_versions:
|
|
139
|
+
if api_version not in [*supported_versions, draft_version]:
|
|
138
140
|
raise ValueError(f"Unsupported standard version {api_version!r}")
|
|
139
141
|
if api_version == "2021.12":
|
|
140
142
|
warnings.warn("The 2021.12 version of the array API specification was requested but the returned namespace is actually version 2022.12", stacklevel=2)
|
|
143
|
+
if api_version == draft_version:
|
|
144
|
+
warnings.warn(f"The {draft_version} version of the array API specification is in draft status. Not all features are implemented in array_api_strict, some functions may not be fully tested, and behaviors are subject to change before the final standard release.")
|
|
141
145
|
API_VERSION = api_version
|
|
142
146
|
array_api_strict.__array_api_version__ = API_VERSION
|
|
143
147
|
|
|
@@ -169,6 +173,7 @@ set_array_api_strict_flags.__doc__ = set_array_api_strict_flags.__doc__.format(
|
|
|
169
173
|
supported_versions=supported_versions,
|
|
170
174
|
default_version=default_version,
|
|
171
175
|
default_extensions=default_extensions,
|
|
176
|
+
draft_version=draft_version,
|
|
172
177
|
)
|
|
173
178
|
|
|
174
179
|
def get_array_api_strict_flags():
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from ._array_object import Array
|
|
4
4
|
from ._dtypes import _integer_dtypes
|
|
5
|
+
from ._flags import requires_api_version
|
|
5
6
|
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
@@ -25,3 +26,14 @@ def take(x: Array, indices: Array, /, *, axis: Optional[int] = None) -> Array:
|
|
|
25
26
|
if x.device != indices.device:
|
|
26
27
|
raise ValueError(f"Arrays from two different devices ({x.device} and {indices.device}) can not be combined.")
|
|
27
28
|
return Array._new(np.take(x._array, indices._array, axis=axis), device=x.device)
|
|
29
|
+
|
|
30
|
+
@requires_api_version('2024.12')
|
|
31
|
+
def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array:
|
|
32
|
+
"""
|
|
33
|
+
Array API compatible wrapper for :py:func:`np.take_along_axis <numpy.take_along_axis>`.
|
|
34
|
+
|
|
35
|
+
See its docstring for more information.
|
|
36
|
+
"""
|
|
37
|
+
if x.device != indices.device:
|
|
38
|
+
raise ValueError(f"Arrays from two different devices ({x.device} and {indices.device}) can not be combined.")
|
|
39
|
+
return Array._new(np.take_along_axis(x._array, indices._array, axis), device=x.device)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from typing import Optional, Union, Tuple, List
|
|
9
|
+
from ._typing import device, DefaultDataTypes, DataTypes, Capabilities
|
|
10
|
+
|
|
11
|
+
from ._array_object import ALL_DEVICES, CPU_DEVICE
|
|
12
|
+
from ._flags import get_array_api_strict_flags, requires_api_version
|
|
13
|
+
from ._dtypes import bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128
|
|
14
|
+
|
|
15
|
+
@requires_api_version('2023.12')
|
|
16
|
+
class __array_namespace_info__:
|
|
17
|
+
@requires_api_version('2023.12')
|
|
18
|
+
def capabilities(self) -> Capabilities:
|
|
19
|
+
flags = get_array_api_strict_flags()
|
|
20
|
+
res = {"boolean indexing": flags['boolean_indexing'],
|
|
21
|
+
"data-dependent shapes": flags['data_dependent_shapes'],
|
|
22
|
+
}
|
|
23
|
+
if flags['api_version'] >= '2024.12':
|
|
24
|
+
# maxdims is 32 for NumPy 1.x and 64 for NumPy 2.0. Eventually we will
|
|
25
|
+
# drop support for NumPy 1 but for now, just compute the number
|
|
26
|
+
# directly
|
|
27
|
+
for i in range(1, 100):
|
|
28
|
+
try:
|
|
29
|
+
np.zeros((1,)*i)
|
|
30
|
+
except ValueError:
|
|
31
|
+
maxdims = i - 1
|
|
32
|
+
break
|
|
33
|
+
else:
|
|
34
|
+
raise RuntimeError("Could not get max dimensions (this is a bug in array-api-strict)")
|
|
35
|
+
res['max dimensions'] = maxdims
|
|
36
|
+
return res
|
|
37
|
+
|
|
38
|
+
@requires_api_version('2023.12')
|
|
39
|
+
def default_device(self) -> device:
|
|
40
|
+
return CPU_DEVICE
|
|
41
|
+
|
|
42
|
+
@requires_api_version('2023.12')
|
|
43
|
+
def default_dtypes(
|
|
44
|
+
self,
|
|
45
|
+
*,
|
|
46
|
+
device: Optional[device] = None,
|
|
47
|
+
) -> DefaultDataTypes:
|
|
48
|
+
return {
|
|
49
|
+
"real floating": float64,
|
|
50
|
+
"complex floating": complex128,
|
|
51
|
+
"integral": int64,
|
|
52
|
+
"indexing": int64,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@requires_api_version('2023.12')
|
|
56
|
+
def dtypes(
|
|
57
|
+
self,
|
|
58
|
+
*,
|
|
59
|
+
device: Optional[device] = None,
|
|
60
|
+
kind: Optional[Union[str, Tuple[str, ...]]] = None,
|
|
61
|
+
) -> DataTypes:
|
|
62
|
+
if kind is None:
|
|
63
|
+
return {
|
|
64
|
+
"bool": bool,
|
|
65
|
+
"int8": int8,
|
|
66
|
+
"int16": int16,
|
|
67
|
+
"int32": int32,
|
|
68
|
+
"int64": int64,
|
|
69
|
+
"uint8": uint8,
|
|
70
|
+
"uint16": uint16,
|
|
71
|
+
"uint32": uint32,
|
|
72
|
+
"uint64": uint64,
|
|
73
|
+
"float32": float32,
|
|
74
|
+
"float64": float64,
|
|
75
|
+
"complex64": complex64,
|
|
76
|
+
"complex128": complex128,
|
|
77
|
+
}
|
|
78
|
+
if kind == "bool":
|
|
79
|
+
return {"bool": bool}
|
|
80
|
+
if kind == "signed integer":
|
|
81
|
+
return {
|
|
82
|
+
"int8": int8,
|
|
83
|
+
"int16": int16,
|
|
84
|
+
"int32": int32,
|
|
85
|
+
"int64": int64,
|
|
86
|
+
}
|
|
87
|
+
if kind == "unsigned integer":
|
|
88
|
+
return {
|
|
89
|
+
"uint8": uint8,
|
|
90
|
+
"uint16": uint16,
|
|
91
|
+
"uint32": uint32,
|
|
92
|
+
"uint64": uint64,
|
|
93
|
+
}
|
|
94
|
+
if kind == "integral":
|
|
95
|
+
return {
|
|
96
|
+
"int8": int8,
|
|
97
|
+
"int16": int16,
|
|
98
|
+
"int32": int32,
|
|
99
|
+
"int64": int64,
|
|
100
|
+
"uint8": uint8,
|
|
101
|
+
"uint16": uint16,
|
|
102
|
+
"uint32": uint32,
|
|
103
|
+
"uint64": uint64,
|
|
104
|
+
}
|
|
105
|
+
if kind == "real floating":
|
|
106
|
+
return {
|
|
107
|
+
"float32": float32,
|
|
108
|
+
"float64": float64,
|
|
109
|
+
}
|
|
110
|
+
if kind == "complex floating":
|
|
111
|
+
return {
|
|
112
|
+
"complex64": complex64,
|
|
113
|
+
"complex128": complex128,
|
|
114
|
+
}
|
|
115
|
+
if kind == "numeric":
|
|
116
|
+
return {
|
|
117
|
+
"int8": int8,
|
|
118
|
+
"int16": int16,
|
|
119
|
+
"int32": int32,
|
|
120
|
+
"int64": int64,
|
|
121
|
+
"uint8": uint8,
|
|
122
|
+
"uint16": uint16,
|
|
123
|
+
"uint32": uint32,
|
|
124
|
+
"uint64": uint64,
|
|
125
|
+
"float32": float32,
|
|
126
|
+
"float64": float64,
|
|
127
|
+
"complex64": complex64,
|
|
128
|
+
"complex128": complex128,
|
|
129
|
+
}
|
|
130
|
+
if isinstance(kind, tuple):
|
|
131
|
+
res = {}
|
|
132
|
+
for k in kind:
|
|
133
|
+
res.update(self.dtypes(kind=k))
|
|
134
|
+
return res
|
|
135
|
+
raise ValueError(f"unsupported kind: {kind!r}")
|
|
136
|
+
|
|
137
|
+
@requires_api_version('2023.12')
|
|
138
|
+
def devices(self) -> List[device]:
|
|
139
|
+
return list(ALL_DEVICES)
|
|
@@ -21,7 +21,6 @@ import sys
|
|
|
21
21
|
|
|
22
22
|
from typing import (
|
|
23
23
|
Any,
|
|
24
|
-
ModuleType,
|
|
25
24
|
TypedDict,
|
|
26
25
|
TypeVar,
|
|
27
26
|
Protocol,
|
|
@@ -29,6 +28,7 @@ from typing import (
|
|
|
29
28
|
|
|
30
29
|
from ._array_object import Array, _device
|
|
31
30
|
from ._dtypes import _DType
|
|
31
|
+
from ._info import __array_namespace_info__
|
|
32
32
|
|
|
33
33
|
_T_co = TypeVar("_T_co", covariant=True)
|
|
34
34
|
|
|
@@ -41,7 +41,7 @@ Device = _device
|
|
|
41
41
|
|
|
42
42
|
Dtype = _DType
|
|
43
43
|
|
|
44
|
-
Info =
|
|
44
|
+
Info = __array_namespace_info__
|
|
45
45
|
|
|
46
46
|
if sys.version_info >= (3, 12):
|
|
47
47
|
from collections.abc import Buffer as SupportsBufferProtocol
|
|
@@ -54,7 +54,8 @@ class SupportsDLPack(Protocol):
|
|
|
54
54
|
def __dlpack__(self, /, *, stream: None = ...) -> PyCapsule: ...
|
|
55
55
|
|
|
56
56
|
Capabilities = TypedDict(
|
|
57
|
-
"Capabilities", {"boolean indexing": bool, "data-dependent shapes": bool
|
|
57
|
+
"Capabilities", {"boolean indexing": bool, "data-dependent shapes": bool,
|
|
58
|
+
"max dimensions": int}
|
|
58
59
|
)
|
|
59
60
|
|
|
60
61
|
DefaultDataTypes = TypedDict(
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ._array_object import Array
|
|
4
|
+
from ._flags import requires_api_version
|
|
5
|
+
from ._dtypes import _numeric_dtypes
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from typing import Optional, Tuple, Union
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def all(
|
|
15
|
+
x: Array,
|
|
16
|
+
/,
|
|
17
|
+
*,
|
|
18
|
+
axis: Optional[Union[int, Tuple[int, ...]]] = None,
|
|
19
|
+
keepdims: bool = False,
|
|
20
|
+
) -> Array:
|
|
21
|
+
"""
|
|
22
|
+
Array API compatible wrapper for :py:func:`np.all <numpy.all>`.
|
|
23
|
+
|
|
24
|
+
See its docstring for more information.
|
|
25
|
+
"""
|
|
26
|
+
return Array._new(np.asarray(np.all(x._array, axis=axis, keepdims=keepdims)), device=x.device)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def any(
|
|
30
|
+
x: Array,
|
|
31
|
+
/,
|
|
32
|
+
*,
|
|
33
|
+
axis: Optional[Union[int, Tuple[int, ...]]] = None,
|
|
34
|
+
keepdims: bool = False,
|
|
35
|
+
) -> Array:
|
|
36
|
+
"""
|
|
37
|
+
Array API compatible wrapper for :py:func:`np.any <numpy.any>`.
|
|
38
|
+
|
|
39
|
+
See its docstring for more information.
|
|
40
|
+
"""
|
|
41
|
+
return Array._new(np.asarray(np.any(x._array, axis=axis, keepdims=keepdims)), device=x.device)
|
|
42
|
+
|
|
43
|
+
@requires_api_version('2024.12')
|
|
44
|
+
def diff(
|
|
45
|
+
x: Array,
|
|
46
|
+
/,
|
|
47
|
+
*,
|
|
48
|
+
axis: int = -1,
|
|
49
|
+
n: int = 1,
|
|
50
|
+
prepend: Optional[Array] = None,
|
|
51
|
+
append: Optional[Array] = None,
|
|
52
|
+
) -> Array:
|
|
53
|
+
if x.dtype not in _numeric_dtypes:
|
|
54
|
+
raise TypeError("Only numeric dtypes are allowed in diff")
|
|
55
|
+
|
|
56
|
+
# TODO: The type promotion behavior for prepend and append is not
|
|
57
|
+
# currently specified.
|
|
58
|
+
|
|
59
|
+
# NumPy does not support prepend=None or append=None
|
|
60
|
+
kwargs = dict(axis=axis, n=n)
|
|
61
|
+
if prepend is not None:
|
|
62
|
+
if prepend.device != x.device:
|
|
63
|
+
raise ValueError(f"Arrays from two different devices ({prepend.device} and {x.device}) can not be combined.")
|
|
64
|
+
kwargs['prepend'] = prepend._array
|
|
65
|
+
if append is not None:
|
|
66
|
+
if append.device != x.device:
|
|
67
|
+
raise ValueError(f"Arrays from two different devices ({append.device} and {x.device}) can not be combined.")
|
|
68
|
+
kwargs['append'] = append._array
|
|
69
|
+
return Array._new(np.diff(x._array, **kwargs), device=x.device)
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-11-
|
|
11
|
+
"date": "2024-11-11T15:30:59-0700",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.
|
|
14
|
+
"full-revisionid": "fe4f34ad30ba59c1c981037dd181f6b4daf23b22",
|
|
15
|
+
"version": "2.2"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -364,6 +364,23 @@ def test_array_conversion():
|
|
|
364
364
|
with pytest.raises(RuntimeError, match="Can not convert array"):
|
|
365
365
|
asarray([a])
|
|
366
366
|
|
|
367
|
+
def test__array__():
|
|
368
|
+
# __array__ should work for now
|
|
369
|
+
a = ones((2, 3))
|
|
370
|
+
np.array(a)
|
|
371
|
+
|
|
372
|
+
# Test the _allow_array private global flag for disabling it in the
|
|
373
|
+
# future.
|
|
374
|
+
from .. import _array_object
|
|
375
|
+
original_value = _array_object._allow_array
|
|
376
|
+
try:
|
|
377
|
+
_array_object._allow_array = False
|
|
378
|
+
a = ones((2, 3))
|
|
379
|
+
with pytest.raises(ValueError, match="Conversion from an array_api_strict array to a NumPy ndarray is not supported"):
|
|
380
|
+
np.array(a)
|
|
381
|
+
finally:
|
|
382
|
+
_array_object._allow_array = original_value
|
|
383
|
+
|
|
367
384
|
def test_allow_newaxis():
|
|
368
385
|
a = ones(5)
|
|
369
386
|
indexed_a = a[None, :]
|
|
@@ -436,8 +453,12 @@ def test_array_namespace():
|
|
|
436
453
|
assert a.__array_namespace__(api_version="2021.12") is array_api_strict
|
|
437
454
|
assert array_api_strict.__array_api_version__ == "2021.12"
|
|
438
455
|
|
|
456
|
+
with pytest.warns(UserWarning):
|
|
457
|
+
assert a.__array_namespace__(api_version="2024.12") is array_api_strict
|
|
458
|
+
assert array_api_strict.__array_api_version__ == "2024.12"
|
|
459
|
+
|
|
439
460
|
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2021.11"))
|
|
440
|
-
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="
|
|
461
|
+
pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2025.12"))
|
|
441
462
|
|
|
442
463
|
def test_iter():
|
|
443
464
|
pytest.raises(TypeError, lambda: iter(asarray(3)))
|
|
@@ -448,7 +469,7 @@ def test_iter():
|
|
|
448
469
|
pytest.raises(TypeError, lambda: iter(ones((3, 3))))
|
|
449
470
|
|
|
450
471
|
@pytest.mark.parametrize("api_version", ['2021.12', '2022.12', '2023.12'])
|
|
451
|
-
def
|
|
472
|
+
def test_dlpack_2023_12(api_version):
|
|
452
473
|
if api_version == '2021.12':
|
|
453
474
|
with pytest.warns(UserWarning):
|
|
454
475
|
set_array_api_strict_flags(api_version=api_version)
|
|
@@ -456,19 +477,41 @@ def dlpack_2023_12(api_version):
|
|
|
456
477
|
set_array_api_strict_flags(api_version=api_version)
|
|
457
478
|
|
|
458
479
|
a = asarray([1, 2, 3], dtype=int8)
|
|
459
|
-
|
|
460
|
-
# Do not error
|
|
480
|
+
# Never an error
|
|
461
481
|
a.__dlpack__()
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
482
|
+
|
|
483
|
+
if api_version < '2023.12':
|
|
484
|
+
pytest.raises(ValueError, lambda:
|
|
485
|
+
a.__dlpack__(dl_device=a.__dlpack_device__()))
|
|
486
|
+
pytest.raises(ValueError, lambda:
|
|
487
|
+
a.__dlpack__(dl_device=None))
|
|
488
|
+
pytest.raises(ValueError, lambda:
|
|
489
|
+
a.__dlpack__(max_version=(1, 0)))
|
|
490
|
+
pytest.raises(ValueError, lambda:
|
|
491
|
+
a.__dlpack__(max_version=None))
|
|
492
|
+
pytest.raises(ValueError, lambda:
|
|
493
|
+
a.__dlpack__(copy=False))
|
|
494
|
+
pytest.raises(ValueError, lambda:
|
|
495
|
+
a.__dlpack__(copy=True))
|
|
496
|
+
pytest.raises(ValueError, lambda:
|
|
497
|
+
a.__dlpack__(copy=None))
|
|
498
|
+
elif np.lib.NumpyVersion(np.__version__) < '2.1.0':
|
|
499
|
+
pytest.raises(NotImplementedError, lambda:
|
|
500
|
+
a.__dlpack__(dl_device=CPU_DEVICE))
|
|
501
|
+
a.__dlpack__(dl_device=None)
|
|
502
|
+
pytest.raises(NotImplementedError, lambda:
|
|
503
|
+
a.__dlpack__(max_version=(1, 0)))
|
|
504
|
+
a.__dlpack__(max_version=None)
|
|
505
|
+
pytest.raises(NotImplementedError, lambda:
|
|
506
|
+
a.__dlpack__(copy=False))
|
|
507
|
+
pytest.raises(NotImplementedError, lambda:
|
|
508
|
+
a.__dlpack__(copy=True))
|
|
509
|
+
a.__dlpack__(copy=None)
|
|
510
|
+
else:
|
|
511
|
+
a.__dlpack__(dl_device=a.__dlpack_device__())
|
|
512
|
+
a.__dlpack__(dl_device=None)
|
|
513
|
+
a.__dlpack__(max_version=(1, 0))
|
|
514
|
+
a.__dlpack__(max_version=None)
|
|
515
|
+
a.__dlpack__(copy=False)
|
|
516
|
+
a.__dlpack__(copy=True)
|
|
517
|
+
a.__dlpack__(copy=None)
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_elementwise_functions.py
RENAMED
|
@@ -2,6 +2,8 @@ from inspect import signature, getmodule
|
|
|
2
2
|
|
|
3
3
|
from numpy.testing import assert_raises
|
|
4
4
|
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
5
7
|
from .. import asarray, _elementwise_functions
|
|
6
8
|
from .._elementwise_functions import bitwise_left_shift, bitwise_right_shift
|
|
7
9
|
from .._dtypes import (
|
|
@@ -79,10 +81,12 @@ elementwise_function_input_types = {
|
|
|
79
81
|
"minimum": "real numeric",
|
|
80
82
|
"multiply": "numeric",
|
|
81
83
|
"negative": "numeric",
|
|
84
|
+
"nextafter": "real floating-point",
|
|
82
85
|
"not_equal": "all",
|
|
83
86
|
"positive": "numeric",
|
|
84
87
|
"pow": "numeric",
|
|
85
88
|
"real": "complex floating-point",
|
|
89
|
+
"reciprocal": "floating-point",
|
|
86
90
|
"remainder": "real numeric",
|
|
87
91
|
"round": "numeric",
|
|
88
92
|
"sign": "numeric",
|
|
@@ -126,7 +130,8 @@ def test_function_device_persists():
|
|
|
126
130
|
yield asarray(1., dtype=d)
|
|
127
131
|
|
|
128
132
|
# Use the latest version of the standard so all functions are included
|
|
129
|
-
|
|
133
|
+
with pytest.warns(UserWarning):
|
|
134
|
+
set_array_api_strict_flags(api_version="2024.12")
|
|
130
135
|
|
|
131
136
|
for func_name, types in elementwise_function_input_types.items():
|
|
132
137
|
dtypes = _dtype_categories[types]
|
|
@@ -162,7 +167,8 @@ def test_function_types():
|
|
|
162
167
|
yield asarray(1.0, dtype=d)
|
|
163
168
|
|
|
164
169
|
# Use the latest version of the standard so all functions are included
|
|
165
|
-
|
|
170
|
+
with pytest.warns(UserWarning):
|
|
171
|
+
set_array_api_strict_flags(api_version="2024.12")
|
|
166
172
|
|
|
167
173
|
for x in _array_vals():
|
|
168
174
|
for func_name, types in elementwise_function_input_types.items():
|
|
@@ -3,8 +3,6 @@ import subprocess
|
|
|
3
3
|
|
|
4
4
|
from .._flags import (set_array_api_strict_flags, get_array_api_strict_flags,
|
|
5
5
|
reset_array_api_strict_flags)
|
|
6
|
-
from .._info import (capabilities, default_device, default_dtypes, devices,
|
|
7
|
-
dtypes)
|
|
8
6
|
from .._fft import (fft, ifft, fftn, ifftn, rfft, irfft, rfftn, irfftn, hfft,
|
|
9
7
|
ihfft, fftfreq, rfftfreq, fftshift, ifftshift)
|
|
10
8
|
from .._linalg import (cholesky, cross, det, diagonal, eigh, eigvalsh, inv,
|
|
@@ -99,6 +97,21 @@ def test_flags_api_version_2023_12():
|
|
|
99
97
|
'enabled_extensions': ('linalg', 'fft'),
|
|
100
98
|
}
|
|
101
99
|
|
|
100
|
+
def test_flags_api_version_2024_12():
|
|
101
|
+
# Make sure setting the version to 2024.12 issues a warning.
|
|
102
|
+
with pytest.warns(UserWarning) as record:
|
|
103
|
+
set_array_api_strict_flags(api_version='2024.12')
|
|
104
|
+
assert len(record) == 1
|
|
105
|
+
assert '2024.12' in str(record[0].message)
|
|
106
|
+
assert 'draft' in str(record[0].message)
|
|
107
|
+
flags = get_array_api_strict_flags()
|
|
108
|
+
assert flags == {
|
|
109
|
+
'api_version': '2024.12',
|
|
110
|
+
'boolean_indexing': True,
|
|
111
|
+
'data_dependent_shapes': True,
|
|
112
|
+
'enabled_extensions': ('linalg', 'fft'),
|
|
113
|
+
}
|
|
114
|
+
|
|
102
115
|
def test_setting_flags_invalid():
|
|
103
116
|
# Test setting flags with invalid values
|
|
104
117
|
pytest.raises(ValueError, lambda:
|
|
@@ -245,14 +258,17 @@ def test_fft(func_name):
|
|
|
245
258
|
set_array_api_strict_flags(enabled_extensions=('fft',))
|
|
246
259
|
func()
|
|
247
260
|
|
|
261
|
+
# Test functionality even if the info object is already created
|
|
262
|
+
_info = xp.__array_namespace_info__()
|
|
263
|
+
|
|
248
264
|
api_version_2023_12_examples = {
|
|
249
265
|
'__array_namespace_info__': lambda: xp.__array_namespace_info__(),
|
|
250
266
|
# Test these functions directly to ensure they are properly decorated
|
|
251
|
-
'capabilities': capabilities,
|
|
252
|
-
'default_device': default_device,
|
|
253
|
-
'default_dtypes': default_dtypes,
|
|
254
|
-
'devices': devices,
|
|
255
|
-
'dtypes': dtypes,
|
|
267
|
+
'capabilities': _info.capabilities,
|
|
268
|
+
'default_device': _info.default_device,
|
|
269
|
+
'default_dtypes': _info.default_dtypes,
|
|
270
|
+
'devices': _info.devices,
|
|
271
|
+
'dtypes': _info.dtypes,
|
|
256
272
|
'clip': lambda: xp.clip(xp.asarray([1, 2, 3]), 1, 2),
|
|
257
273
|
'copysign': lambda: xp.copysign(xp.asarray([1., 2., 3.]), xp.asarray([-1., -1., -1.])),
|
|
258
274
|
'cumulative_sum': lambda: xp.cumulative_sum(xp.asarray([1, 2, 3])),
|
|
@@ -285,6 +301,36 @@ def test_api_version_2023_12(func_name):
|
|
|
285
301
|
set_array_api_strict_flags(api_version='2022.12')
|
|
286
302
|
pytest.raises(RuntimeError, func)
|
|
287
303
|
|
|
304
|
+
api_version_2024_12_examples = {
|
|
305
|
+
'diff': lambda: xp.diff(xp.asarray([0, 1, 2])),
|
|
306
|
+
'nextafter': lambda: xp.nextafter(xp.asarray(0.), xp.asarray(1.)),
|
|
307
|
+
'reciprocal': lambda: xp.reciprocal(xp.asarray([2.])),
|
|
308
|
+
'take_along_axis': lambda: xp.take_along_axis(xp.zeros((2, 3)),
|
|
309
|
+
xp.zeros((1, 4), dtype=xp.int64)),
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@pytest.mark.parametrize('func_name', api_version_2024_12_examples.keys())
|
|
313
|
+
def test_api_version_2024_12(func_name):
|
|
314
|
+
func = api_version_2024_12_examples[func_name]
|
|
315
|
+
|
|
316
|
+
# By default, these functions should error
|
|
317
|
+
pytest.raises(RuntimeError, func)
|
|
318
|
+
|
|
319
|
+
# In 2022.12 and 2023.12, these functions should error
|
|
320
|
+
set_array_api_strict_flags(api_version='2022.12')
|
|
321
|
+
pytest.raises(RuntimeError, func)
|
|
322
|
+
set_array_api_strict_flags(api_version='2023.12')
|
|
323
|
+
pytest.raises(RuntimeError, func)
|
|
324
|
+
|
|
325
|
+
# They should not error in 2024.12
|
|
326
|
+
with pytest.warns(UserWarning):
|
|
327
|
+
set_array_api_strict_flags(api_version='2024.12')
|
|
328
|
+
func()
|
|
329
|
+
|
|
330
|
+
# Test the behavior gets updated properly
|
|
331
|
+
set_array_api_strict_flags(api_version='2023.12')
|
|
332
|
+
pytest.raises(RuntimeError, func)
|
|
333
|
+
|
|
288
334
|
def test_disabled_extensions():
|
|
289
335
|
# Test that xp.extension errors when an extension is disabled, and that
|
|
290
336
|
# xp.__all__ is updated properly.
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: array_api_strict
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2
|
|
4
4
|
Summary: A strict, minimal implementation of the Python array API standard.
|
|
5
5
|
Home-page: https://data-apis.org/array-api-strict/
|
|
6
6
|
Author: Consortium for Python Data API Standards
|
|
7
7
|
License: MIT
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
13
|
Classifier: License :: OSI Approved :: BSD License
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.9
|
|
17
16
|
Description-Content-Type: text/markdown
|
|
18
17
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: numpy
|
|
18
|
+
Requires-Dist: numpy
|
|
20
19
|
|
|
21
20
|
# array-api-strict
|
|
22
21
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numpy
|
|
@@ -15,15 +15,14 @@ setup(
|
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
16
16
|
url="https://data-apis.org/array-api-strict/",
|
|
17
17
|
license="MIT",
|
|
18
|
-
python_requires=">=3.
|
|
19
|
-
install_requires=["numpy
|
|
18
|
+
python_requires=">=3.9",
|
|
19
|
+
install_requires=["numpy"],
|
|
20
20
|
classifiers=[
|
|
21
21
|
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
22
23
|
"Programming Language :: Python :: 3.10",
|
|
23
24
|
"Programming Language :: Python :: 3.11",
|
|
24
25
|
"Programming Language :: Python :: 3.12",
|
|
25
|
-
"Programming Language :: Python :: 3.13",
|
|
26
|
-
"Intended Audience :: Developers",
|
|
27
26
|
"License :: OSI Approved :: BSD License",
|
|
28
27
|
"Operating System :: OS Independent",
|
|
29
28
|
],
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
from typing import Optional, Union, Tuple, List
|
|
7
|
-
from ._typing import device, DefaultDataTypes, DataTypes, Capabilities, Info
|
|
8
|
-
|
|
9
|
-
from ._array_object import ALL_DEVICES, CPU_DEVICE
|
|
10
|
-
from ._flags import get_array_api_strict_flags, requires_api_version
|
|
11
|
-
from ._dtypes import bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128
|
|
12
|
-
|
|
13
|
-
@requires_api_version('2023.12')
|
|
14
|
-
def __array_namespace_info__() -> Info:
|
|
15
|
-
import array_api_strict._info
|
|
16
|
-
return array_api_strict._info
|
|
17
|
-
|
|
18
|
-
@requires_api_version('2023.12')
|
|
19
|
-
def capabilities() -> Capabilities:
|
|
20
|
-
flags = get_array_api_strict_flags()
|
|
21
|
-
return {"boolean indexing": flags['boolean_indexing'],
|
|
22
|
-
"data-dependent shapes": flags['data_dependent_shapes'],
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@requires_api_version('2023.12')
|
|
26
|
-
def default_device() -> device:
|
|
27
|
-
return CPU_DEVICE
|
|
28
|
-
|
|
29
|
-
@requires_api_version('2023.12')
|
|
30
|
-
def default_dtypes(
|
|
31
|
-
*,
|
|
32
|
-
device: Optional[device] = None,
|
|
33
|
-
) -> DefaultDataTypes:
|
|
34
|
-
return {
|
|
35
|
-
"real floating": float64,
|
|
36
|
-
"complex floating": complex128,
|
|
37
|
-
"integral": int64,
|
|
38
|
-
"indexing": int64,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
@requires_api_version('2023.12')
|
|
42
|
-
def dtypes(
|
|
43
|
-
*,
|
|
44
|
-
device: Optional[device] = None,
|
|
45
|
-
kind: Optional[Union[str, Tuple[str, ...]]] = None,
|
|
46
|
-
) -> DataTypes:
|
|
47
|
-
if kind is None:
|
|
48
|
-
return {
|
|
49
|
-
"bool": bool,
|
|
50
|
-
"int8": int8,
|
|
51
|
-
"int16": int16,
|
|
52
|
-
"int32": int32,
|
|
53
|
-
"int64": int64,
|
|
54
|
-
"uint8": uint8,
|
|
55
|
-
"uint16": uint16,
|
|
56
|
-
"uint32": uint32,
|
|
57
|
-
"uint64": uint64,
|
|
58
|
-
"float32": float32,
|
|
59
|
-
"float64": float64,
|
|
60
|
-
"complex64": complex64,
|
|
61
|
-
"complex128": complex128,
|
|
62
|
-
}
|
|
63
|
-
if kind == "bool":
|
|
64
|
-
return {"bool": bool}
|
|
65
|
-
if kind == "signed integer":
|
|
66
|
-
return {
|
|
67
|
-
"int8": int8,
|
|
68
|
-
"int16": int16,
|
|
69
|
-
"int32": int32,
|
|
70
|
-
"int64": int64,
|
|
71
|
-
}
|
|
72
|
-
if kind == "unsigned integer":
|
|
73
|
-
return {
|
|
74
|
-
"uint8": uint8,
|
|
75
|
-
"uint16": uint16,
|
|
76
|
-
"uint32": uint32,
|
|
77
|
-
"uint64": uint64,
|
|
78
|
-
}
|
|
79
|
-
if kind == "integral":
|
|
80
|
-
return {
|
|
81
|
-
"int8": int8,
|
|
82
|
-
"int16": int16,
|
|
83
|
-
"int32": int32,
|
|
84
|
-
"int64": int64,
|
|
85
|
-
"uint8": uint8,
|
|
86
|
-
"uint16": uint16,
|
|
87
|
-
"uint32": uint32,
|
|
88
|
-
"uint64": uint64,
|
|
89
|
-
}
|
|
90
|
-
if kind == "real floating":
|
|
91
|
-
return {
|
|
92
|
-
"float32": float32,
|
|
93
|
-
"float64": float64,
|
|
94
|
-
}
|
|
95
|
-
if kind == "complex floating":
|
|
96
|
-
return {
|
|
97
|
-
"complex64": complex64,
|
|
98
|
-
"complex128": complex128,
|
|
99
|
-
}
|
|
100
|
-
if kind == "numeric":
|
|
101
|
-
return {
|
|
102
|
-
"int8": int8,
|
|
103
|
-
"int16": int16,
|
|
104
|
-
"int32": int32,
|
|
105
|
-
"int64": int64,
|
|
106
|
-
"uint8": uint8,
|
|
107
|
-
"uint16": uint16,
|
|
108
|
-
"uint32": uint32,
|
|
109
|
-
"uint64": uint64,
|
|
110
|
-
"float32": float32,
|
|
111
|
-
"float64": float64,
|
|
112
|
-
"complex64": complex64,
|
|
113
|
-
"complex128": complex128,
|
|
114
|
-
}
|
|
115
|
-
if isinstance(kind, tuple):
|
|
116
|
-
res = {}
|
|
117
|
-
for k in kind:
|
|
118
|
-
res.update(dtypes(kind=k))
|
|
119
|
-
return res
|
|
120
|
-
raise ValueError(f"unsupported kind: {kind!r}")
|
|
121
|
-
|
|
122
|
-
@requires_api_version('2023.12')
|
|
123
|
-
def devices() -> List[device]:
|
|
124
|
-
return list(ALL_DEVICES)
|
|
125
|
-
|
|
126
|
-
__all__ = [
|
|
127
|
-
"capabilities",
|
|
128
|
-
"default_device",
|
|
129
|
-
"default_dtypes",
|
|
130
|
-
"devices",
|
|
131
|
-
"dtypes",
|
|
132
|
-
]
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from ._array_object import Array
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
if TYPE_CHECKING:
|
|
7
|
-
from typing import Optional, Tuple, Union
|
|
8
|
-
|
|
9
|
-
import numpy as np
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def all(
|
|
13
|
-
x: Array,
|
|
14
|
-
/,
|
|
15
|
-
*,
|
|
16
|
-
axis: Optional[Union[int, Tuple[int, ...]]] = None,
|
|
17
|
-
keepdims: bool = False,
|
|
18
|
-
) -> Array:
|
|
19
|
-
"""
|
|
20
|
-
Array API compatible wrapper for :py:func:`np.all <numpy.all>`.
|
|
21
|
-
|
|
22
|
-
See its docstring for more information.
|
|
23
|
-
"""
|
|
24
|
-
return Array._new(np.asarray(np.all(x._array, axis=axis, keepdims=keepdims)), device=x.device)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def any(
|
|
28
|
-
x: Array,
|
|
29
|
-
/,
|
|
30
|
-
*,
|
|
31
|
-
axis: Optional[Union[int, Tuple[int, ...]]] = None,
|
|
32
|
-
keepdims: bool = False,
|
|
33
|
-
) -> Array:
|
|
34
|
-
"""
|
|
35
|
-
Array API compatible wrapper for :py:func:`np.any <numpy.any>`.
|
|
36
|
-
|
|
37
|
-
See its docstring for more information.
|
|
38
|
-
"""
|
|
39
|
-
return Array._new(np.asarray(np.any(x._array, axis=axis, keepdims=keepdims)), device=x.device)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
numpy>=2.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/_linear_algebra_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_creation_functions.py
RENAMED
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_data_type_functions.py
RENAMED
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_device_support.py
RENAMED
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_indexing_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_set_functions.py
RENAMED
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_sorting_functions.py
RENAMED
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict/tests/test_statistical_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{array_api_strict-2.1.2 → array_api_strict-2.2}/array_api_strict.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|