You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`array-api-extra` is a collection of additional utilities and tools that are
74
81
missing from the Array API Standard but can be useful for compliant array
@@ -103,7 +110,8 @@ reference implementation.
103
110
{ref}`array-api-tests` is a test suite which verifies that your API
104
111
for adhering to the standard. For each function or method it confirms
105
112
it's importable, verifies the signature, and generates multiple test
106
-
cases with hypothesis package and runs asserts for the outputs.
113
+
cases with [hypothesis](https://hypothesis.readthedocs.io/en/latest/)
114
+
package and runs asserts for the outputs.
107
115
108
116
The setup details are enclosed in the GitHub repository, so here we
109
117
cover only the minimal workflow:
@@ -113,17 +121,20 @@ cover only the minimal workflow:
113
121
variable to your package import name.
114
122
3. Inside the `array-api-tests` directory run `pytest` command. There are
115
123
multiple useful options delivered by the test suite, a few worth mentioning:
116
-
-`--max-examples=2` - maximal number of test cases to generate by the
124
+
-`--max-examples=1000` - maximal number of test cases to generate by the
117
125
hypothesis. This allows you to balance between execution time of the test
118
-
suite and thoroughness of the testing.
126
+
suite and thoroughness of the testing. It's advised to use as many examples
127
+
as the time buget can fit. Each test case is a random combination of
128
+
possible inputs: the more cases, the higher chance of finding an unsupported
129
+
edge case.
119
130
- With `--xfails-file` option you can describe which tests are expected to
120
131
fail - it's impossible to get the whole API perfectly implemented on a
121
132
first try, so tracking what still fails gives you more control over the
122
133
state of your API.
123
134
-`-o xfail_strict=<bool>` is often used with the previous one. If a test
124
135
expected to fail actually passes (`XPASS`) then you can decide whether
125
136
to ignore that fact or raise it as an error.
126
-
-`--skips-file` for skipping files. At times some failing tests might stall
137
+
-`--skips-file` for skipping tests. At times some failing tests might stall
127
138
the execution time of the test suite - in that case the most convenient
128
139
option is to skip these for the time being.
129
140
@@ -138,15 +149,15 @@ A simpler, and more manual, way of testing the Array API coverage is to
138
149
run your API calls along with {ref}`array-api-strict` Python implementation.
139
150
140
151
This way you can ensure the outputs coming from your API match the minimal
141
-
reference implementation, but bare in mind you need to write the tests cases
152
+
reference implementation, but bear in mind you need to write the tests cases
142
153
yourself, so you need to also take into account the edge cases as well.
143
154
144
155
145
156
(array-consumers)=
146
157
147
158
## Array Consumers
148
159
149
-
For array consumers the main premise is keep in mind that your **array
160
+
For array consumers the main premise is to keep in mind that your **array
150
161
manipulation operations should not lock in for a particular array producing
151
162
library**. For instance, if you use NumPy for arrays, then your code could
152
163
contain:
@@ -162,8 +173,9 @@ return np.dot(c, b)
162
173
163
174
The first step should be as simple as assigning `np` namespace to a dedicated
164
175
namespace variable - the convention in the ecosystem is to name it `xp`. Then
165
-
Making sure that each method and function call is something that Array API
166
-
supports is vital (we will get to that soon):
176
+
making sure that each method and function call is something that Array API
177
+
supports is vital. `dot` is present in the NumPy's API but the standard doesn't
178
+
support it. Let's use `tensordot` instead - both NumPy and the standard define it:
167
179
168
180
```python
169
181
import numpy as np
@@ -180,12 +192,23 @@ Then replacing one backend with another one should rely on providing a different
180
192
namespace, such as: `xp = torch`, e.g. via environment variable. This can be useful
181
193
if you're writing a script or in your custom software. The other alternatives are:
182
194
183
-
- If you are building a library where the backend is determined by input arrays
184
-
passed by the end-user, then a recommended way is to ask your input arrays for a
185
-
namespace to use: `xp = arr.__array_namespace__()`
186
-
- Each function you implement can have a namespace `xp` as a parameter in the
187
-
signature. Then enforcing inputs to be of type by the provided backend can be
188
-
achieved with `arg1 = xp.asarray(arg1)` for each input array.
195
+
- If you are building a library where the backend is determined by input arrays,
196
+
and your function accepts array arguments, then a recommended way is to ask
197
+
your input arrays for a namespace to use: `xp = arr.__array_namespace__()`.
198
+
If the given library doesn't have it, then [`array_api_compat.array_namespace()`](https://data-apis.org/array-api-compat/helper-functions.html#array_api_compat.array_namespace)
199
+
should be used instead:
200
+
```python
201
+
deffunc(array1, scalar1, scalar2):
202
+
xp = array1.__array_namespace__() # or array_namespace(array1)
203
+
return xp.arange(scalar1, scalar2) @ array1
204
+
```
205
+
- For a function that accepts scalars and returns arrays, use namespace `xp` as
206
+
a parameter in the signature. Then enforcing objects to be of type by the
207
+
provided backend can be achieved with `arg1 = xp.asarray(arg1)` for each input:
208
+
```python
209
+
deffunc(s1, s2, xp):
210
+
return xp.arange(s1, s2)
211
+
```
189
212
190
213
If you're relying on NumPy, CuPy, PyTorch, Dask, or JAX then
191
214
{ref}`array-api-compat` can come in handy for the transition. The compat layer
0 commit comments