array-api-strict 2.1.3__py3-none-any.whl → 2.2__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.
@@ -172,10 +172,12 @@ from ._elementwise_functions import (
172
172
  minimum,
173
173
  multiply,
174
174
  negative,
175
+ nextafter,
175
176
  not_equal,
176
177
  positive,
177
178
  pow,
178
179
  real,
180
+ reciprocal,
179
181
  remainder,
180
182
  round,
181
183
  sign,
@@ -240,10 +242,12 @@ __all__ += [
240
242
  "minimum",
241
243
  "multiply",
242
244
  "negative",
245
+ "nextafter",
243
246
  "not_equal",
244
247
  "positive",
245
248
  "pow",
246
249
  "real",
250
+ "reciprocal",
247
251
  "remainder",
248
252
  "round",
249
253
  "sign",
@@ -258,9 +262,9 @@ __all__ += [
258
262
  "trunc",
259
263
  ]
260
264
 
261
- from ._indexing_functions import take
265
+ from ._indexing_functions import take, take_along_axis
262
266
 
263
- __all__ += ["take"]
267
+ __all__ += ["take", "take_along_axis"]
264
268
 
265
269
  from ._info import __array_namespace_info__
266
270
 
@@ -305,9 +309,9 @@ from ._statistical_functions import cumulative_sum, max, mean, min, prod, std, s
305
309
 
306
310
  __all__ += ["cumulative_sum", "max", "mean", "min", "prod", "std", "sum", "var"]
307
311
 
308
- from ._utility_functions import all, any
312
+ from ._utility_functions import all, any, diff
309
313
 
310
- __all__ += ["all", "any"]
314
+ __all__ += ["all", "any", "diff"]
311
315
 
312
316
  from ._array_object import Device
313
317
  __all__ += ["Device"]
@@ -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}``. The default version number is
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)
array_api_strict/_info.py CHANGED
@@ -2,131 +2,138 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ import numpy as np
6
+
5
7
  if TYPE_CHECKING:
6
8
  from typing import Optional, Union, Tuple, List
7
- from ._typing import device, DefaultDataTypes, DataTypes, Capabilities, Info
9
+ from ._typing import device, DefaultDataTypes, DataTypes, Capabilities
8
10
 
9
11
  from ._array_object import ALL_DEVICES, CPU_DEVICE
10
12
  from ._flags import get_array_api_strict_flags, requires_api_version
11
13
  from ._dtypes import bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128
12
14
 
13
15
  @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
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
28
37
 
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
- }
38
+ @requires_api_version('2023.12')
39
+ def default_device(self) -> device:
40
+ return CPU_DEVICE
40
41
 
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":
42
+ @requires_api_version('2023.12')
43
+ def default_dtypes(
44
+ self,
45
+ *,
46
+ device: Optional[device] = None,
47
+ ) -> DefaultDataTypes:
80
48
  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,
49
+ "real floating": float64,
50
+ "complex floating": complex128,
51
+ "integral": int64,
52
+ "indexing": int64,
89
53
  }
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
54
 
122
- @requires_api_version('2023.12')
123
- def devices() -> List[device]:
124
- return list(ALL_DEVICES)
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}")
125
136
 
126
- __all__ = [
127
- "capabilities",
128
- "default_device",
129
- "default_dtypes",
130
- "devices",
131
- "dtypes",
132
- ]
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 = ModuleType
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(
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from ._array_object import Array
4
+ from ._flags import requires_api_version
5
+ from ._dtypes import _numeric_dtypes
4
6
 
5
7
  from typing import TYPE_CHECKING
6
8
  if TYPE_CHECKING:
@@ -37,3 +39,31 @@ def any(
37
39
  See its docstring for more information.
38
40
  """
39
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-08T16:00:41-0700",
11
+ "date": "2024-11-11T15:30:59-0700",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "310bb626b04ea61e24feca146440dd4ec1f6cf5b",
15
- "version": "2.1.3"
14
+ "full-revisionid": "fe4f34ad30ba59c1c981037dd181f6b4daf23b22",
15
+ "version": "2.2"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -453,8 +453,12 @@ def test_array_namespace():
453
453
  assert a.__array_namespace__(api_version="2021.12") is array_api_strict
454
454
  assert array_api_strict.__array_api_version__ == "2021.12"
455
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
+
456
460
  pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2021.11"))
457
- pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2024.12"))
461
+ pytest.raises(ValueError, lambda: a.__array_namespace__(api_version="2025.12"))
458
462
 
459
463
  def test_iter():
460
464
  pytest.raises(TypeError, lambda: iter(asarray(3)))
@@ -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
- set_array_api_strict_flags(api_version="2023.12")
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
- set_array_api_strict_flags(api_version="2023.12")
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: array_api_strict
3
- Version: 2.1.3
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
@@ -1,14 +1,14 @@
1
- array_api_strict/__init__.py,sha256=iQRjMJ4h-MoNqhxYeerCVRPORO6W6KePiQ8xIeecDac,6788
1
+ array_api_strict/__init__.py,sha256=Nm_8GFfA0bpkVMw3urULYSadngGPaW6C2VuEpM-ziyI,6904
2
2
  array_api_strict/_array_object.py,sha256=Q69HJ8qdQqqugWIRf4RsifZUEypbhNV_y5EVSygmbrQ,52571
3
3
  array_api_strict/_constants.py,sha256=AYayN2jf1Dp5rXZ7WPBdUhtPBo_JMCi-pD9oW5zmFkI,87
4
4
  array_api_strict/_creation_functions.py,sha256=A9TTvPSznF9NsxT0Pd_G9yU6IZAfW1tpBkFMYoJyguw,12985
5
5
  array_api_strict/_data_type_functions.py,sha256=sKxKRQiwoXPwQJPbiN5BhF9rbc3ZtXfjRuglB7VsIgo,7016
6
6
  array_api_strict/_dtypes.py,sha256=QDGo9rqiS_o3quv7QRFM0j6DkvOjRauQ1Ymikwlu8Ns,6213
7
- array_api_strict/_elementwise_functions.py,sha256=g9YecX4gM4V6UCjl7b7I752EFXhRusjm-EKGZ12jDeI,38651
7
+ array_api_strict/_elementwise_functions.py,sha256=epo92ppRP4XDcDhS431J599NA1pT4DK08wIdV9vVO8s,39713
8
8
  array_api_strict/_fft.py,sha256=xH1o4j_amq3e1yGVChV6vms7oAfCzpzB18I-IzjNSXw,9702
9
- array_api_strict/_flags.py,sha256=hXe5cTFNlFEgbB4nsEazbAPFwnsFnn52wGRYRDjfCFg,13121
10
- array_api_strict/_indexing_functions.py,sha256=VORFyAFCZjLpL6gZ_PNVNKbQjpjhIXQDNDDHf7Mjy_U,970
11
- array_api_strict/_info.py,sha256=WWvUjNITc5-jLyS4KrnwTidD3baD9DjHseV254hCUY0,3567
9
+ array_api_strict/_flags.py,sha256=lUb-SowhHvA9MLBm0ICO5L7M7FgclWPF8v8z5N--Q_o,13558
10
+ array_api_strict/_indexing_functions.py,sha256=3AqC8Mgi9BakrStlZoIV34d0Au5dMk6qT07TxpvvCGk,1520
11
+ array_api_strict/_info.py,sha256=QvW1PV7dO2oGPWAerG3wJn61QAqjqxx4iHkWPUturI4,4455
12
12
  array_api_strict/_linalg.py,sha256=sfmd5fuq2nHy_9kD2QQ23_JbbVZo7LHFgb10qjrr7nw,19846
13
13
  array_api_strict/_linear_algebra_functions.py,sha256=12XPBU27X3WZdaq9Ob2eUmL_PxMzDNF76pY4iESlPyo,3872
14
14
  array_api_strict/_manipulation_functions.py,sha256=Pa1gVRlaSC39-Zd6n4Q8c9P0anZYdyCh95Wyx3az3lc,6681
@@ -16,17 +16,17 @@ array_api_strict/_searching_functions.py,sha256=32IiLLpa91N-jtzaxj4Nw9nQgF2ROkcN
16
16
  array_api_strict/_set_functions.py,sha256=PZVsxkRQi5Zi104dI2fHZBFqpluOAW0IJzzdJSyajiI,3295
17
17
  array_api_strict/_sorting_functions.py,sha256=GG7g2NYCFn2G2fFS6ZdfYOWpuuSIrdZdJWEuL72_-LI,2065
18
18
  array_api_strict/_statistical_functions.py,sha256=dMJ-x8TQW5MD2rFYCmRH6QthA2KDKXjhkj4hcbd3LSU,5148
19
- array_api_strict/_typing.py,sha256=TpmU57g3EAPY9PT6hJEhzBduVrwXJUWvmoBlhy5bQuQ,1803
20
- array_api_strict/_utility_functions.py,sha256=khxtvqPWSDpNp65VgoJUtO4zEfTiGfZZGu_MHwyfmmI,913
21
- array_api_strict/_version.py,sha256=xJzT1_4sE3FOyJjocQQw38msTHLnEXjUj33S0uEZQ5M,497
19
+ array_api_strict/_typing.py,sha256=oaHM01VhgC5JIHxXMouEEajNs0OXtwOasnIznK7z9fk,1889
20
+ array_api_strict/_utility_functions.py,sha256=Mu07FogReaAFToPMHE_j90YBEDEvxD5jPcMK3zeUiG0,2007
21
+ array_api_strict/_version.py,sha256=20M94v12DlLnRLp4vkFO-TkQKxHY21bls4ZgOvbf7jE,495
22
22
  array_api_strict/tests/__init__.py,sha256=t_2GZ3lKcsu4ec4GMKPUDYaeMUJyDquBlQAcPgj7kFE,282
23
23
  array_api_strict/tests/conftest.py,sha256=-wIDryl2MdRLdSonU1G1xWssNq2TFKiWuHquNasXYA8,468
24
- array_api_strict/tests/test_array_object.py,sha256=zzXoGDAHEdK8PBmp9owwoydlcKyIDMHFYg2e9XmjYrU,21685
24
+ array_api_strict/tests/test_array_object.py,sha256=IzfVo63eiPoFFwb4woNT15e4gJFfYVyD7zK-wddRMBY,21865
25
25
  array_api_strict/tests/test_creation_functions.py,sha256=ve0MeqZPrG2dmCG3hTVhap1YgIW-lAaSZIJ_ZoOV9cQ,8323
26
26
  array_api_strict/tests/test_data_type_functions.py,sha256=pLAtm96gpAduNVqq-914JvjAollzhBp4YojVfNScBzs,2138
27
27
  array_api_strict/tests/test_device_support.py,sha256=zpfhHxeRREoXfp0qZTlilm2ZceBc71uCKea1GMVe-ZU,855
28
- array_api_strict/tests/test_elementwise_functions.py,sha256=bKw3b4G-v3yEmmUW2HNXRRQ2tbEPopkrUKbvF8jvUpI,6943
29
- array_api_strict/tests/test_flags.py,sha256=mdy6srnFdLbmpo3SJbW2i7uTPggTlCz5qy9UMAyNGCE,16864
28
+ array_api_strict/tests/test_elementwise_functions.py,sha256=ManUmYZF3oT-UXH4lqWJna3zDHdxVBeuvIdFlFPABQ4,7114
29
+ array_api_strict/tests/test_flags.py,sha256=YadbyJEu7DmMo3TKl3nROf7R4xDIrQfm8acifHA3CYc,18598
30
30
  array_api_strict/tests/test_indexing_functions.py,sha256=C23FnuowVDC1OBuDH06pvsd61qM2dTpTwzw6UgC4BoY,1281
31
31
  array_api_strict/tests/test_linalg.py,sha256=CJ4JnCkWyysMUAih3PI-ZZeOH-X39H0p-RKBoEwk6Jw,5675
32
32
  array_api_strict/tests/test_manipulation_functions.py,sha256=CzcudVxUKhQ4Ec94Vda4C6HaAqrOQPQfQxT4uTM2fsM,1064
@@ -34,8 +34,8 @@ array_api_strict/tests/test_set_functions.py,sha256=ikzab1j3SXxGf0OqwHrOAM13HwQe
34
34
  array_api_strict/tests/test_sorting_functions.py,sha256=1xvQBKts5KTKYc-puMITX9iR_KTbzzVB8fY-SObad_Y,899
35
35
  array_api_strict/tests/test_statistical_functions.py,sha256=JwS4DhASt5T0YUNtbFK2nSXgDrVVZx1tVpe7LU2aPK4,1365
36
36
  array_api_strict/tests/test_validation.py,sha256=JdsK4z1M0U5YoJrfWSzOpEhmlehvZHF5SG0I0k6oDy8,672
37
- array_api_strict-2.1.3.dist-info/LICENSE,sha256=djDm4UfHAJmycwFUNyUmrTdRkrFF9Ac8uqIlbxH7j5Y,1585
38
- array_api_strict-2.1.3.dist-info/METADATA,sha256=cup_jx9CNgdyj14hC3Nou6-C7w7Lte1AqHZ58Fzc1Ug,1595
39
- array_api_strict-2.1.3.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
40
- array_api_strict-2.1.3.dist-info/top_level.txt,sha256=M4cE8VLgRHp_d9TPkbk7_I4JriELFdEJz-NKJJqAkAE,17
41
- array_api_strict-2.1.3.dist-info/RECORD,,
37
+ array_api_strict-2.2.dist-info/LICENSE,sha256=djDm4UfHAJmycwFUNyUmrTdRkrFF9Ac8uqIlbxH7j5Y,1585
38
+ array_api_strict-2.2.dist-info/METADATA,sha256=uCWtV4ZiiCzUkNRWapj10LpJxUCPHy8fzddfOiFt2cM,1593
39
+ array_api_strict-2.2.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
40
+ array_api_strict-2.2.dist-info/top_level.txt,sha256=M4cE8VLgRHp_d9TPkbk7_I4JriELFdEJz-NKJJqAkAE,17
41
+ array_api_strict-2.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5