array-api-strict 1.1__tar.gz → 2.0__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.
Files changed (51) hide show
  1. array_api_strict-2.0/PKG-INFO +41 -0
  2. array_api_strict-2.0/README.md +22 -0
  3. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/__init__.py +71 -16
  4. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_array_object.py +71 -16
  5. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_creation_functions.py +66 -40
  6. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_data_type_functions.py +16 -4
  7. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_elementwise_functions.py +135 -0
  8. array_api_strict-1.1/array_api_strict/fft.py → array_api_strict-2.0/array_api_strict/_fft.py +17 -1
  9. array_api_strict-2.0/array_api_strict/_flags.py +370 -0
  10. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_indexing_functions.py +5 -0
  11. array_api_strict-2.0/array_api_strict/_info.py +132 -0
  12. array_api_strict-1.1/array_api_strict/linalg.py → array_api_strict-2.0/array_api_strict/_linalg.py +69 -60
  13. array_api_strict-2.0/array_api_strict/_linear_algebra_functions.py +81 -0
  14. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_manipulation_functions.py +71 -2
  15. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_searching_functions.py +27 -1
  16. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_set_functions.py +6 -0
  17. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_statistical_functions.py +50 -16
  18. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_typing.py +38 -4
  19. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_utility_functions.py +3 -1
  20. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_version.py +3 -3
  21. array_api_strict-2.0/array_api_strict/tests/conftest.py +16 -0
  22. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_array_object.py +58 -1
  23. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_creation_functions.py +25 -1
  24. array_api_strict-2.0/array_api_strict/tests/test_data_type_functions.py +70 -0
  25. array_api_strict-2.0/array_api_strict/tests/test_elementwise_functions.py +132 -0
  26. array_api_strict-2.0/array_api_strict/tests/test_flags.py +493 -0
  27. array_api_strict-2.0/array_api_strict/tests/test_linalg.py +133 -0
  28. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_manipulation_functions.py +1 -2
  29. array_api_strict-2.0/array_api_strict/tests/test_statistical_functions.py +29 -0
  30. array_api_strict-2.0/array_api_strict.egg-info/PKG-INFO +41 -0
  31. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict.egg-info/SOURCES.txt +9 -2
  32. array_api_strict-1.1/PKG-INFO +0 -216
  33. array_api_strict-1.1/README.md +0 -197
  34. array_api_strict-1.1/array_api_strict/tests/test_data_type_functions.py +0 -40
  35. array_api_strict-1.1/array_api_strict/tests/test_elementwise_functions.py +0 -114
  36. array_api_strict-1.1/array_api_strict.egg-info/PKG-INFO +0 -216
  37. {array_api_strict-1.1 → array_api_strict-2.0}/LICENSE +0 -0
  38. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_constants.py +0 -0
  39. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_dtypes.py +0 -0
  40. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/_sorting_functions.py +0 -0
  41. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/__init__.py +0 -0
  42. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_indexing_functions.py +0 -0
  43. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_set_functions.py +0 -0
  44. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_sorting_functions.py +0 -0
  45. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict/tests/test_validation.py +0 -0
  46. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict.egg-info/dependency_links.txt +0 -0
  47. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict.egg-info/requires.txt +0 -0
  48. {array_api_strict-1.1 → array_api_strict-2.0}/array_api_strict.egg-info/top_level.txt +0 -0
  49. {array_api_strict-1.1 → array_api_strict-2.0}/setup.cfg +0 -0
  50. {array_api_strict-1.1 → array_api_strict-2.0}/setup.py +0 -0
  51. {array_api_strict-1.1 → array_api_strict-2.0}/versioneer.py +0 -0
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.1
2
+ Name: array_api_strict
3
+ Version: 2.0
4
+ Summary: A strict, minimal implementation of the Python array API standard.
5
+ Home-page: https://data-apis.org/array-api-strict/
6
+ Author: Consortium for Python Data API Standards
7
+ License: MIT
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: License :: OSI Approved :: BSD License
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: numpy
19
+
20
+ # array-api-strict
21
+
22
+ `array_api_strict` is a strict, minimal implementation of the [Python array
23
+ API](https://data-apis.org/array-api/latest/).
24
+
25
+ The purpose of array-api-strict is to provide an implementation of the array
26
+ API for consuming libraries to test against so they can be completely sure
27
+ their usage of the array API is portable.
28
+
29
+ It is *not* intended to be used by end-users. End-users of the array API
30
+ should just use their favorite array library (NumPy, CuPy, PyTorch, etc.) as
31
+ usual. It is also not intended to be used as a dependency by consuming
32
+ libraries. Consuming library code should use the
33
+ [array-api-compat](https://data-apis.org/array-api-compat/) package to
34
+ support the array API. Rather, it is intended to be used in the test suites of
35
+ consuming libraries to test their array API usage.
36
+
37
+ array-api-strict currently supports the 2022.12 version of the standard.
38
+ 2023.12 support is planned and is tracked by [this
39
+ issue](https://github.com/data-apis/array-api-strict/issues/25).
40
+
41
+ See the documentation for more details https://data-apis.org/array-api-strict/
@@ -0,0 +1,22 @@
1
+ # array-api-strict
2
+
3
+ `array_api_strict` is a strict, minimal implementation of the [Python array
4
+ API](https://data-apis.org/array-api/latest/).
5
+
6
+ The purpose of array-api-strict is to provide an implementation of the array
7
+ API for consuming libraries to test against so they can be completely sure
8
+ their usage of the array API is portable.
9
+
10
+ It is *not* intended to be used by end-users. End-users of the array API
11
+ should just use their favorite array library (NumPy, CuPy, PyTorch, etc.) as
12
+ usual. It is also not intended to be used as a dependency by consuming
13
+ libraries. Consuming library code should use the
14
+ [array-api-compat](https://data-apis.org/array-api-compat/) package to
15
+ support the array API. Rather, it is intended to be used in the test suites of
16
+ consuming libraries to test their array API usage.
17
+
18
+ array-api-strict currently supports the 2022.12 version of the standard.
19
+ 2023.12 support is planned and is tracked by [this
20
+ issue](https://github.com/data-apis/array-api-strict/issues/25).
21
+
22
+ See the documentation for more details https://data-apis.org/array-api-strict/
@@ -10,15 +10,21 @@ It is *not* intended to be used by end-users. End-users of the array API
10
10
  should just use their favorite array library (NumPy, CuPy, PyTorch, etc.) as
11
11
  usual. It is also not intended to be used as a dependency by consuming
12
12
  libraries. Consuming library code should use the
13
- array-api-compat (https://github.com/data-apis/array-api-compat) package to
13
+ array-api-compat (https://data-apis.org/array-api-compat/) package to
14
14
  support the array API. Rather, it is intended to be used in the test suites of
15
15
  consuming libraries to test their array API usage.
16
16
 
17
17
  """
18
18
 
19
- __array_api_version__ = "2022.12"
19
+ __all__ = []
20
20
 
21
- __all__ = ["__array_api_version__"]
21
+ # Warning: __array_api_version__ could change globally with
22
+ # set_array_api_strict_flags(). This should always be accessed as an
23
+ # attribute, like xp.__array_api_version__, or using
24
+ # array_api_strict.get_array_api_strict_flags()['api_version'].
25
+ from ._flags import API_VERSION as __array_api_version__
26
+
27
+ __all__ += ["__array_api_version__"]
22
28
 
23
29
  from ._constants import e, inf, nan, pi, newaxis
24
30
 
@@ -79,6 +85,7 @@ __all__ += [
79
85
  "broadcast_to",
80
86
  "can_cast",
81
87
  "finfo",
88
+ "isdtype",
82
89
  "iinfo",
83
90
  "result_type",
84
91
  ]
@@ -110,6 +117,8 @@ __all__ += [
110
117
  "uint64",
111
118
  "float32",
112
119
  "float64",
120
+ "complex64",
121
+ "complex128",
113
122
  "bool",
114
123
  ]
115
124
 
@@ -130,7 +139,9 @@ from ._elementwise_functions import (
130
139
  bitwise_right_shift,
131
140
  bitwise_xor,
132
141
  ceil,
142
+ clip,
133
143
  conj,
144
+ copysign,
134
145
  cos,
135
146
  cosh,
136
147
  divide,
@@ -141,6 +152,7 @@ from ._elementwise_functions import (
141
152
  floor_divide,
142
153
  greater,
143
154
  greater_equal,
155
+ hypot,
144
156
  imag,
145
157
  isfinite,
146
158
  isinf,
@@ -156,6 +168,8 @@ from ._elementwise_functions import (
156
168
  logical_not,
157
169
  logical_or,
158
170
  logical_xor,
171
+ maximum,
172
+ minimum,
159
173
  multiply,
160
174
  negative,
161
175
  not_equal,
@@ -165,6 +179,7 @@ from ._elementwise_functions import (
165
179
  remainder,
166
180
  round,
167
181
  sign,
182
+ signbit,
168
183
  sin,
169
184
  sinh,
170
185
  square,
@@ -192,6 +207,9 @@ __all__ += [
192
207
  "bitwise_right_shift",
193
208
  "bitwise_xor",
194
209
  "ceil",
210
+ "clip",
211
+ "conj",
212
+ "copysign",
195
213
  "cos",
196
214
  "cosh",
197
215
  "divide",
@@ -202,6 +220,8 @@ __all__ += [
202
220
  "floor_divide",
203
221
  "greater",
204
222
  "greater_equal",
223
+ "hypot",
224
+ "imag",
205
225
  "isfinite",
206
226
  "isinf",
207
227
  "isnan",
@@ -216,14 +236,18 @@ __all__ += [
216
236
  "logical_not",
217
237
  "logical_or",
218
238
  "logical_xor",
239
+ "maximum",
240
+ "minimum",
219
241
  "multiply",
220
242
  "negative",
221
243
  "not_equal",
222
244
  "positive",
223
245
  "pow",
246
+ "real",
224
247
  "remainder",
225
248
  "round",
226
249
  "sign",
250
+ "signbit",
227
251
  "sin",
228
252
  "sinh",
229
253
  "square",
@@ -238,35 +262,36 @@ from ._indexing_functions import take
238
262
 
239
263
  __all__ += ["take"]
240
264
 
241
- # linalg is an extension in the array API spec, which is a sub-namespace. Only
242
- # a subset of functions in it are imported into the top-level namespace.
243
- from . import linalg
265
+ from ._info import __array_namespace_info__
244
266
 
245
- __all__ += ["linalg"]
267
+ __all__ += [
268
+ "__array_namespace_info__",
269
+ ]
246
270
 
247
- from .linalg import matmul, tensordot, matrix_transpose, vecdot
271
+ from ._linear_algebra_functions import matmul, tensordot, matrix_transpose, vecdot
248
272
 
249
273
  __all__ += ["matmul", "tensordot", "matrix_transpose", "vecdot"]
250
274
 
251
- from . import fft
252
- __all__ += ["fft"]
253
-
254
275
  from ._manipulation_functions import (
255
276
  concat,
256
277
  expand_dims,
257
278
  flip,
279
+ moveaxis,
258
280
  permute_dims,
281
+ repeat,
259
282
  reshape,
260
283
  roll,
261
284
  squeeze,
262
285
  stack,
286
+ tile,
287
+ unstack,
263
288
  )
264
289
 
265
- __all__ += ["concat", "expand_dims", "flip", "permute_dims", "reshape", "roll", "squeeze", "stack"]
290
+ __all__ += ["concat", "expand_dims", "flip", "moveaxis", "permute_dims", "repeat", "reshape", "roll", "squeeze", "stack", "tile", "unstack"]
266
291
 
267
- from ._searching_functions import argmax, argmin, nonzero, where
292
+ from ._searching_functions import argmax, argmin, nonzero, searchsorted, where
268
293
 
269
- __all__ += ["argmax", "argmin", "nonzero", "where"]
294
+ __all__ += ["argmax", "argmin", "nonzero", "searchsorted", "where"]
270
295
 
271
296
  from ._set_functions import unique_all, unique_counts, unique_inverse, unique_values
272
297
 
@@ -276,14 +301,44 @@ from ._sorting_functions import argsort, sort
276
301
 
277
302
  __all__ += ["argsort", "sort"]
278
303
 
279
- from ._statistical_functions import max, mean, min, prod, std, sum, var
304
+ from ._statistical_functions import cumulative_sum, max, mean, min, prod, std, sum, var
280
305
 
281
- __all__ += ["max", "mean", "min", "prod", "std", "sum", "var"]
306
+ __all__ += ["cumulative_sum", "max", "mean", "min", "prod", "std", "sum", "var"]
282
307
 
283
308
  from ._utility_functions import all, any
284
309
 
285
310
  __all__ += ["all", "any"]
286
311
 
312
+ # Helper functions that are not part of the standard
313
+
314
+ from ._flags import (
315
+ set_array_api_strict_flags,
316
+ get_array_api_strict_flags,
317
+ reset_array_api_strict_flags,
318
+ ArrayAPIStrictFlags,
319
+ )
320
+
321
+ __all__ += ['set_array_api_strict_flags', 'get_array_api_strict_flags', 'reset_array_api_strict_flags', 'ArrayAPIStrictFlags']
322
+
287
323
  from . import _version
288
324
  __version__ = _version.get_versions()['version']
289
325
  del _version
326
+
327
+
328
+ # Extensions can be enabled or disabled dynamically. In order to make
329
+ # "array_api_strict.linalg" give an AttributeError when it is disabled, we
330
+ # use __getattr__. Note that linalg and fft are dynamically added and removed
331
+ # from __all__ in set_array_api_strict_flags.
332
+
333
+ def __getattr__(name):
334
+ if name in ['linalg', 'fft']:
335
+ if name in get_array_api_strict_flags()['enabled_extensions']:
336
+ if name == 'linalg':
337
+ from . import _linalg
338
+ return _linalg
339
+ elif name == 'fft':
340
+ from . import _fft
341
+ return _fft
342
+ else:
343
+ raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict")
344
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -17,6 +17,7 @@ from __future__ import annotations
17
17
 
18
18
  import operator
19
19
  from enum import IntEnum
20
+
20
21
  from ._creation_functions import asarray
21
22
  from ._dtypes import (
22
23
  _DType,
@@ -30,12 +31,14 @@ from ._dtypes import (
30
31
  _result_type,
31
32
  _dtype_categories,
32
33
  )
34
+ from ._flags import get_array_api_strict_flags, set_array_api_strict_flags
33
35
 
34
- from typing import TYPE_CHECKING, Optional, Tuple, Union, Any, SupportsIndex
36
+ from typing import TYPE_CHECKING, SupportsIndex
35
37
  import types
36
38
 
37
39
  if TYPE_CHECKING:
38
- from ._typing import Any, PyCapsule, Device, Dtype
40
+ from typing import Optional, Tuple, Union, Any
41
+ from ._typing import PyCapsule, Device, Dtype
39
42
  import numpy.typing as npt
40
43
 
41
44
  import numpy as np
@@ -48,6 +51,8 @@ class _cpu_device:
48
51
 
49
52
  CPU_DEVICE = _cpu_device()
50
53
 
54
+ _default = object()
55
+
51
56
  class Array:
52
57
  """
53
58
  n-d array object for the array API namespace.
@@ -425,13 +430,17 @@ class Array:
425
430
  "the Array API)"
426
431
  )
427
432
  elif isinstance(i, Array):
428
- if i.dtype in _boolean_dtypes and len(_key) != 1:
429
- assert isinstance(key, tuple) # sanity check
430
- raise IndexError(
431
- f"Single-axes index {i} is a boolean array and "
432
- f"{len(key)=}, but masking is only specified in the "
433
- "Array API when the array is the sole index."
434
- )
433
+ if i.dtype in _boolean_dtypes:
434
+ if len(_key) != 1:
435
+ assert isinstance(key, tuple) # sanity check
436
+ raise IndexError(
437
+ f"Single-axes index {i} is a boolean array and "
438
+ f"{len(key)=}, but masking is only specified in the "
439
+ "Array API when the array is the sole index."
440
+ )
441
+ if not get_array_api_strict_flags()['boolean_indexing']:
442
+ raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict")
443
+
435
444
  elif i.dtype in _integer_dtypes and i.ndim != 0:
436
445
  raise IndexError(
437
446
  f"Single-axes index {i} is a non-zero-dimensional "
@@ -480,8 +489,21 @@ class Array:
480
489
  def __array_namespace__(
481
490
  self: Array, /, *, api_version: Optional[str] = None
482
491
  ) -> types.ModuleType:
483
- if api_version is not None and not api_version.startswith("2021."):
484
- raise ValueError(f"Unrecognized array API version: {api_version!r}")
492
+ """
493
+ Return the array_api_strict namespace corresponding to api_version.
494
+
495
+ The default API version is '2022.12'. Note that '2021.12' is supported,
496
+ but currently identical to '2022.12'.
497
+
498
+ For array_api_strict, calling this function with api_version will set
499
+ the API version for the array_api_strict module globally. This can
500
+ also be achieved with the
501
+ {func}`array_api_strict.set_array_api_strict_flags` function. If you
502
+ want to only set the version locally, use the
503
+ {class}`array_api_strict.ArrayApiStrictFlags` context manager.
504
+
505
+ """
506
+ set_array_api_strict_flags(api_version=api_version)
485
507
  import array_api_strict
486
508
  return array_api_strict
487
509
 
@@ -505,10 +527,34 @@ class Array:
505
527
  res = self._array.__complex__()
506
528
  return res
507
529
 
508
- def __dlpack__(self: Array, /, *, stream: None = None) -> PyCapsule:
530
+ def __dlpack__(
531
+ self: Array,
532
+ /,
533
+ *,
534
+ stream: Optional[Union[int, Any]] = None,
535
+ max_version: Optional[tuple[int, int]] = _default,
536
+ dl_device: Optional[tuple[IntEnum, int]] = _default,
537
+ copy: Optional[bool] = _default,
538
+ ) -> PyCapsule:
509
539
  """
510
540
  Performs the operation __dlpack__.
511
541
  """
542
+ if get_array_api_strict_flags()['api_version'] < '2023.12':
543
+ if max_version is not _default:
544
+ raise ValueError("The max_version argument to __dlpack__ requires at least version 2023.12 of the array API")
545
+ if dl_device is not _default:
546
+ raise ValueError("The device argument to __dlpack__ requires at least version 2023.12 of the array API")
547
+ if copy is not _default:
548
+ raise ValueError("The copy argument to __dlpack__ requires at least version 2023.12 of the array API")
549
+
550
+ # Going to wait for upstream numpy support
551
+ if max_version not in [_default, None]:
552
+ raise NotImplementedError("The max_version argument to __dlpack__ is not yet implemented")
553
+ if dl_device not in [_default, None]:
554
+ raise NotImplementedError("The device argument to __dlpack__ is not yet implemented")
555
+ if copy not in [_default, None]:
556
+ raise NotImplementedError("The copy argument to __dlpack__ is not yet implemented")
557
+
512
558
  return self._array.__dlpack__(stream=stream)
513
559
 
514
560
  def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]:
@@ -570,8 +616,8 @@ class Array:
570
616
  key: Union[
571
617
  int,
572
618
  slice,
573
- ellipsis,
574
- Tuple[Union[int, slice, ellipsis, None], ...],
619
+ ellipsis, # noqa: F821
620
+ Tuple[Union[int, slice, ellipsis, None], ...], # noqa: F821
575
621
  Array,
576
622
  ],
577
623
  /,
@@ -627,6 +673,15 @@ class Array:
627
673
  res = self._array.__invert__()
628
674
  return self.__class__._new(res)
629
675
 
676
+ def __iter__(self: Array, /):
677
+ """
678
+ Performs the operation __iter__.
679
+ """
680
+ # Manually disable iteration, since __getitem__ raises IndexError on
681
+ # things like ones((3, 3))[0], which causes list(ones((3, 3))) to give
682
+ # [].
683
+ raise TypeError("array iteration is not allowed in array-api-strict")
684
+
630
685
  def __le__(self: Array, other: Union[int, float, Array], /) -> Array:
631
686
  """
632
687
  Performs the operation __le__.
@@ -761,7 +816,7 @@ class Array:
761
816
  def __setitem__(
762
817
  self,
763
818
  key: Union[
764
- int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], Array
819
+ int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], Array # noqa: F821
765
820
  ],
766
821
  value: Union[int, float, bool, Array],
767
822
  /,
@@ -1113,7 +1168,7 @@ class Array:
1113
1168
  # Note: mT is new in array API spec (see matrix_transpose)
1114
1169
  @property
1115
1170
  def mT(self) -> Array:
1116
- from .linalg import matrix_transpose
1171
+ from ._linear_algebra_functions import matrix_transpose
1117
1172
  return matrix_transpose(self)
1118
1173
 
1119
1174
  @property
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
12
12
  SupportsBufferProtocol,
13
13
  )
14
14
  from ._dtypes import _DType, _all_dtypes
15
+ from ._flags import get_array_api_strict_flags
15
16
 
16
17
  import numpy as np
17
18
 
@@ -19,7 +20,7 @@ import numpy as np
19
20
  def _check_valid_dtype(dtype):
20
21
  # Note: Only spelling dtypes as the dtype objects is supported.
21
22
  if dtype not in (None,) + _all_dtypes:
22
- raise ValueError("dtype must be one of the supported dtypes")
23
+ raise ValueError(f"dtype must be one of the supported dtypes, got {dtype!r}")
23
24
 
24
25
  def _supports_buffer_protocol(obj):
25
26
  try:
@@ -28,6 +29,14 @@ def _supports_buffer_protocol(obj):
28
29
  return False
29
30
  return True
30
31
 
32
+ def _check_device(device):
33
+ # _array_object imports in this file are inside the functions to avoid
34
+ # circular imports
35
+ from ._array_object import CPU_DEVICE
36
+
37
+ if device not in [CPU_DEVICE, None]:
38
+ raise ValueError(f"Unsupported device {device!r}")
39
+
31
40
  def asarray(
32
41
  obj: Union[
33
42
  Array,
@@ -48,16 +57,13 @@ def asarray(
48
57
 
49
58
  See its docstring for more information.
50
59
  """
51
- # _array_object imports in this file are inside the functions to avoid
52
- # circular imports
53
- from ._array_object import Array, CPU_DEVICE
60
+ from ._array_object import Array
54
61
 
55
62
  _check_valid_dtype(dtype)
56
63
  _np_dtype = None
57
64
  if dtype is not None:
58
65
  _np_dtype = dtype._np_dtype
59
- if device not in [CPU_DEVICE, None]:
60
- raise ValueError(f"Unsupported device {device!r}")
66
+ _check_device(device)
61
67
 
62
68
  if np.__version__[0] < '2':
63
69
  if copy is False:
@@ -106,11 +112,11 @@ def arange(
106
112
 
107
113
  See its docstring for more information.
108
114
  """
109
- from ._array_object import Array, CPU_DEVICE
115
+ from ._array_object import Array
110
116
 
111
117
  _check_valid_dtype(dtype)
112
- if device not in [CPU_DEVICE, None]:
113
- raise ValueError(f"Unsupported device {device!r}")
118
+ _check_device(device)
119
+
114
120
  if dtype is not None:
115
121
  dtype = dtype._np_dtype
116
122
  return Array._new(np.arange(start, stop=stop, step=step, dtype=dtype))
@@ -127,11 +133,11 @@ def empty(
127
133
 
128
134
  See its docstring for more information.
129
135
  """
130
- from ._array_object import Array, CPU_DEVICE
136
+ from ._array_object import Array
131
137
 
132
138
  _check_valid_dtype(dtype)
133
- if device not in [CPU_DEVICE, None]:
134
- raise ValueError(f"Unsupported device {device!r}")
139
+ _check_device(device)
140
+
135
141
  if dtype is not None:
136
142
  dtype = dtype._np_dtype
137
143
  return Array._new(np.empty(shape, dtype=dtype))
@@ -145,11 +151,11 @@ def empty_like(
145
151
 
146
152
  See its docstring for more information.
147
153
  """
148
- from ._array_object import Array, CPU_DEVICE
154
+ from ._array_object import Array
149
155
 
150
156
  _check_valid_dtype(dtype)
151
- if device not in [CPU_DEVICE, None]:
152
- raise ValueError(f"Unsupported device {device!r}")
157
+ _check_device(device)
158
+
153
159
  if dtype is not None:
154
160
  dtype = dtype._np_dtype
155
161
  return Array._new(np.empty_like(x._array, dtype=dtype))
@@ -169,19 +175,39 @@ def eye(
169
175
 
170
176
  See its docstring for more information.
171
177
  """
172
- from ._array_object import Array, CPU_DEVICE
178
+ from ._array_object import Array
173
179
 
174
180
  _check_valid_dtype(dtype)
175
- if device not in [CPU_DEVICE, None]:
176
- raise ValueError(f"Unsupported device {device!r}")
181
+ _check_device(device)
182
+
177
183
  if dtype is not None:
178
184
  dtype = dtype._np_dtype
179
185
  return Array._new(np.eye(n_rows, M=n_cols, k=k, dtype=dtype))
180
186
 
181
187
 
182
- def from_dlpack(x: object, /) -> Array:
188
+ _default = object()
189
+
190
+ def from_dlpack(
191
+ x: object,
192
+ /,
193
+ *,
194
+ device: Optional[Device] = _default,
195
+ copy: Optional[bool] = _default,
196
+ ) -> Array:
183
197
  from ._array_object import Array
184
198
 
199
+ if get_array_api_strict_flags()['api_version'] < '2023.12':
200
+ if device is not _default:
201
+ raise ValueError("The device argument to from_dlpack requires at least version 2023.12 of the array API")
202
+ if copy is not _default:
203
+ raise ValueError("The copy argument to from_dlpack requires at least version 2023.12 of the array API")
204
+
205
+ # Going to wait for upstream numpy support
206
+ if device is not _default:
207
+ _check_device(device)
208
+ if copy not in [_default, None]:
209
+ raise NotImplementedError("The copy argument to from_dlpack is not yet implemented")
210
+
185
211
  return Array._new(np.from_dlpack(x))
186
212
 
187
213
 
@@ -197,11 +223,11 @@ def full(
197
223
 
198
224
  See its docstring for more information.
199
225
  """
200
- from ._array_object import Array, CPU_DEVICE
226
+ from ._array_object import Array
201
227
 
202
228
  _check_valid_dtype(dtype)
203
- if device not in [CPU_DEVICE, None]:
204
- raise ValueError(f"Unsupported device {device!r}")
229
+ _check_device(device)
230
+
205
231
  if isinstance(fill_value, Array) and fill_value.ndim == 0:
206
232
  fill_value = fill_value._array
207
233
  if dtype is not None:
@@ -227,11 +253,11 @@ def full_like(
227
253
 
228
254
  See its docstring for more information.
229
255
  """
230
- from ._array_object import Array, CPU_DEVICE
256
+ from ._array_object import Array
231
257
 
232
258
  _check_valid_dtype(dtype)
233
- if device not in [CPU_DEVICE, None]:
234
- raise ValueError(f"Unsupported device {device!r}")
259
+ _check_device(device)
260
+
235
261
  if dtype is not None:
236
262
  dtype = dtype._np_dtype
237
263
  res = np.full_like(x._array, fill_value, dtype=dtype)
@@ -257,11 +283,11 @@ def linspace(
257
283
 
258
284
  See its docstring for more information.
259
285
  """
260
- from ._array_object import Array, CPU_DEVICE
286
+ from ._array_object import Array
261
287
 
262
288
  _check_valid_dtype(dtype)
263
- if device not in [CPU_DEVICE, None]:
264
- raise ValueError(f"Unsupported device {device!r}")
289
+ _check_device(device)
290
+
265
291
  if dtype is not None:
266
292
  dtype = dtype._np_dtype
267
293
  return Array._new(np.linspace(start, stop, num, dtype=dtype, endpoint=endpoint))
@@ -298,11 +324,11 @@ def ones(
298
324
 
299
325
  See its docstring for more information.
300
326
  """
301
- from ._array_object import Array, CPU_DEVICE
327
+ from ._array_object import Array
302
328
 
303
329
  _check_valid_dtype(dtype)
304
- if device not in [CPU_DEVICE, None]:
305
- raise ValueError(f"Unsupported device {device!r}")
330
+ _check_device(device)
331
+
306
332
  if dtype is not None:
307
333
  dtype = dtype._np_dtype
308
334
  return Array._new(np.ones(shape, dtype=dtype))
@@ -316,11 +342,11 @@ def ones_like(
316
342
 
317
343
  See its docstring for more information.
318
344
  """
319
- from ._array_object import Array, CPU_DEVICE
345
+ from ._array_object import Array
320
346
 
321
347
  _check_valid_dtype(dtype)
322
- if device not in [CPU_DEVICE, None]:
323
- raise ValueError(f"Unsupported device {device!r}")
348
+ _check_device(device)
349
+
324
350
  if dtype is not None:
325
351
  dtype = dtype._np_dtype
326
352
  return Array._new(np.ones_like(x._array, dtype=dtype))
@@ -365,11 +391,11 @@ def zeros(
365
391
 
366
392
  See its docstring for more information.
367
393
  """
368
- from ._array_object import Array, CPU_DEVICE
394
+ from ._array_object import Array
369
395
 
370
396
  _check_valid_dtype(dtype)
371
- if device not in [CPU_DEVICE, None]:
372
- raise ValueError(f"Unsupported device {device!r}")
397
+ _check_device(device)
398
+
373
399
  if dtype is not None:
374
400
  dtype = dtype._np_dtype
375
401
  return Array._new(np.zeros(shape, dtype=dtype))
@@ -383,11 +409,11 @@ def zeros_like(
383
409
 
384
410
  See its docstring for more information.
385
411
  """
386
- from ._array_object import Array, CPU_DEVICE
412
+ from ._array_object import Array
387
413
 
388
414
  _check_valid_dtype(dtype)
389
- if device not in [CPU_DEVICE, None]:
390
- raise ValueError(f"Unsupported device {device!r}")
415
+ _check_device(device)
416
+
391
417
  if dtype is not None:
392
418
  dtype = dtype._np_dtype
393
419
  return Array._new(np.zeros_like(x._array, dtype=dtype))