@@ -66,6 +66,8 @@ def __hash__(self):
66
66
67
67
_default = object ()
68
68
69
+ _allow_array = False
70
+
69
71
class Array :
70
72
"""
71
73
n-d array object for the array API namespace.
@@ -145,30 +147,35 @@ def __repr__(self: Array, /) -> str:
145
147
mid = np .array2string (self ._array , separator = ', ' , prefix = prefix , suffix = suffix )
146
148
return prefix + mid + suffix
147
149
148
- # This function is not required by the spec, but we implement it here for
149
- # convenience so that np.asarray(array_api_strict.Array) will work.
150
+ # Disallow __array__, meaning calling `np.func()` on an array_api_strict
151
+ # array will give an error. If we don't explicitly disallow it, NumPy
152
+ # defaults to creating an object dtype array, which would lead to
153
+ # confusing error messages at best and surprising bugs at worst.
154
+ #
155
+ # The alternative of course is to just support __array__, which is what we
156
+ # used to do. But this isn't actually supported by the standard, so it can
157
+ # lead to code assuming np.asarray(other_array) would always work in the
158
+ # standard.
150
159
def __array__ (self , dtype : None | np .dtype [Any ] = None , copy : None | bool = None ) -> npt .NDArray [Any ]:
151
- """
152
- Warning: this method is NOT part of the array API spec. Implementers
153
- of other libraries need not include it, and users should not assume it
154
- will be present in other implementations.
155
-
156
- """
157
- if self ._device != CPU_DEVICE :
158
- raise RuntimeError (f"Can not convert array on the '{ self ._device } ' device to a Numpy array." )
159
- # copy keyword is new in 2.0.0; for older versions don't use it
160
- # retry without that keyword.
161
- if np .__version__ [0 ] < '2' :
162
- return np .asarray (self ._array , dtype = dtype )
163
- elif np .__version__ .startswith ('2.0.0-dev0' ):
164
- # Handle dev version for which we can't know based on version
165
- # number whether or not the copy keyword is supported.
166
- try :
167
- return np .asarray (self ._array , dtype = dtype , copy = copy )
168
- except TypeError :
160
+ # We have to allow this to be internally enabled as there's no other
161
+ # easy way to parse a list of Array objects in asarray().
162
+ if _allow_array :
163
+ if self ._device != CPU_DEVICE :
164
+ raise RuntimeError (f"Can not convert array on the '{ self ._device } ' device to a Numpy array." )
165
+ # copy keyword is new in 2.0.0; for older versions don't use it
166
+ # retry without that keyword.
167
+ if np .__version__ [0 ] < '2' :
169
168
return np .asarray (self ._array , dtype = dtype )
170
- else :
171
- return np .asarray (self ._array , dtype = dtype , copy = copy )
169
+ elif np .__version__ .startswith ('2.0.0-dev0' ):
170
+ # Handle dev version for which we can't know based on version
171
+ # number whether or not the copy keyword is supported.
172
+ try :
173
+ return np .asarray (self ._array , dtype = dtype , copy = copy )
174
+ except TypeError :
175
+ return np .asarray (self ._array , dtype = dtype )
176
+ else :
177
+ return np .asarray (self ._array , dtype = dtype , copy = copy )
178
+ raise ValueError ("Conversion from an array_api_strict array to a NumPy ndarray is not supported" )
172
179
173
180
# These are various helper functions to make the array behavior match the
174
181
# spec in places where it either deviates from or is more strict than
0 commit comments