Skip to content

Commit 2e12b65

Browse files
committed
Update the README
1 parent 6dcb6f7 commit 2e12b65

File tree

1 file changed

+182
-4
lines changed

1 file changed

+182
-4
lines changed

README.md

+182-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,191 @@
1-
array-api-strict
2-
================
1+
# array-api-strict
32

4-
A strict, minimal implementation of the [Python array
3+
`array_api_strict` is a strict, minimal implementation of the [Python array
54
API](https://data-apis.org/array-api/latest/)
65

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://github.com/data-apis/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+
## Install
19+
20+
`array-api-strict` is available on both
21+
[PyPI](https://pypi.org/project/array-api-strict/)
22+
23+
```
24+
python -m pip install array-api-strict
25+
```
26+
27+
and [Conda-forge](https://anaconda.org/conda-forge/array-api-strict)
28+
29+
```
30+
conda install --channel conda-forge array-api-strict
31+
```
32+
33+
array-api-strict supports NumPy 1.26 and (the upcoming) NumPy 2.0.
34+
35+
## Rationale
36+
37+
The array API has many functions and behaviors that are required to be
38+
implemented by conforming libraries, but it does not, in most cases, disallow
39+
implementing additional functions, keyword arguments, and behaviors that
40+
aren't explicitly required by the standard.
41+
42+
However, this poses a problem for consumers of the array API, as they may
43+
accidentally use a function or rely on a behavior which just happens to be
44+
implemented in every array library they test against (e.g., NumPy and
45+
PyTorch), but isn't required by the standard and may not be included in other
46+
libraries.
47+
48+
array-api-strict solves this problem by providing a strict, minimal
49+
implementation of the array API standard. Only those functions and behaviors
50+
that are explicitly *required* by the standard are implemented. For example,
51+
most NumPy functions accept Python scalars as inputs:
52+
53+
```py
54+
>>> import numpy as np
55+
>>> np.sin(0.0)
56+
0.0
57+
```
58+
59+
However, the standard only specifies function inputs on `Array` objects. And
60+
indeed, some libraries, such as PyTorch, do not allow this:
61+
62+
```py
63+
>>> import torch
64+
>>> torch.sin(0.0)
65+
Traceback (most recent call last):
66+
File "<stdin>", line 1, in <module>
67+
TypeError: sin(): argument 'input' (position 1) must be Tensor, not float
68+
```
69+
70+
In array-api-strict, this is also an error:
71+
72+
```py
73+
>>> import array_api_strict as xp
74+
>>> xp.sin(0.0)
75+
Traceback (most recent call last):
76+
...
77+
AttributeError: 'float' object has no attribute 'dtype'
78+
```
79+
80+
Here is an (incomplete) list of the sorts of ways that array-api-strict is
81+
strict/minimal:
82+
83+
- Only those functions and methods that are [defined in the
84+
standard](https://data-apis.org/array-api/draft/API_specification/index.html)
85+
are included.
86+
87+
- In those functions, only the keyword-arguments that are defined by the
88+
standard are included. All signatures in array-api-strict use
89+
[positional-only
90+
arguments](https://data-apis.org/array-api/draft/API_specification/function_and_method_signatures.html#function-and-method-signatures).
91+
As noted above, only array_api_strict array objects are accepted by
92+
functions, except in the places where the standard allows Python scalars
93+
(i.e., functions to not automatically call `asarray` on their inputs).
94+
95+
- Only those [dtypes that are defined in the
96+
standard](https://data-apis.org/array-api/draft/API_specification/data_types.html)
97+
are included.
98+
99+
- All functions and methods reject inputs if the standard does not *require*
100+
the input dtype(s) to be supported. This is one of the most restrictive
101+
aspects of the library. For example, in NumPy, most transcendental functions
102+
like `sin` will accept integer array inputs, but the [standard only requires
103+
them to accept floating-point
104+
inputs](https://data-apis.org/array-api/draft/API_specification/generated/array_api.sin.html#array_api.sin),
105+
so in array-api-strict, `sin(integer_array)` will raise an exception.
106+
107+
- The
108+
[indexing](https://data-apis.org/array-api/draft/API_specification/indexing.html)
109+
semantics required by the standard are not
110+
111+
- There are no distinct "scalar" objects as in NumPy. There are only 0-D
112+
arrays.
113+
114+
- Dtype objects are just empty objects that only implement [equality
115+
comparison](https://data-apis.org/array-api/draft/API_specification/generated/array_api.data_types.__eq__.html).
116+
The way to access dtype objects in the standard is by name, like
117+
`xp.float32`.
118+
119+
- The array object type itself is private and should not be accessed.
120+
Subclassing or otherwise trying to directly initialize this object is not
121+
supported. Arrays should created with one of the [array creation
122+
functions](https://data-apis.org/array-api/draft/API_specification/creation_functions.html)
123+
such as `asarray`.
124+
125+
## Caveats
126+
127+
array-api-strict is a thin pure Python wrapper around NumPy. NumPy 2.0 fully
128+
supports the array API but NumPy 1.26 does not, so many behaviors are wrapped
129+
in NumPy 1.26 to provide array API compatible behavior. Although it is based
130+
on NumPy, mixing NumPy arrays with array-api-strict arrays is not supported.
131+
This should generally raise an error, as it indicates a potential portability
132+
issue, but this hasn't necessarily been tested thoroughly.
133+
134+
1. array-api-strict is validated against the [array API test
135+
suite](https://github.com/data-apis/array-api-tests). However, there may be
136+
a few minor instances where NumPy deviates from the standard in a way that
137+
is inconvenient to workaround in array-api-strict, since it aims to remain
138+
pure Python. You can see the full list of tests that are known to fail in
139+
the [xfails
140+
file](https://github.com/data-apis/array-api-strict/blob/main/array-api-tests-xfails.txt).
141+
142+
The most notable of these is that in NumPy 1.26, the `copy=False` flag is
143+
not implemented for `asarray` and therefore `array_api_strict` raises
144+
`NotImplementedError` in that case.
145+
146+
2. Since NumPy is a CPU-only library, the [device
147+
support](https://data-apis.org/array-api/draft/design_topics/device_support.html)
148+
in array-api-strict is superficial only. `x.device` is always a (private)
149+
`_CPU_DEVICE` object, and `device` keywords to creation functions only
150+
accept either this object or `None`. A future version of array-api-strict
151+
[may add support for a CuPy
152+
backend](https://github.com/data-apis/array-api-strict/issues/5) so that
153+
more significant device support can be tested.
154+
155+
3. Although only array types are expected in array-api-strict functions,
156+
currently most functions do not do extensive type checking on their inputs,
157+
so a sufficiently duck-typed object may pass through silently (or at best,
158+
you may get `AttributeError` instead of `TypeError`). However, all type
159+
signatures have type annotations (based on those from the standard), so
160+
this deviation may be tested with type checking. This [behavior may improve
161+
in the future](https://github.com/data-apis/array-api-strict/issues/6).
162+
163+
4. There are some behaviors in the standard that are not required to be
164+
implemented by libraries that cannot support [data dependent
165+
shapes](https://data-apis.org/array-api/draft/design_topics/data_dependent_output_shapes.html).
166+
This includes [the `unique_*`
167+
functions](https://data-apis.org/array-api/draft/API_specification/set_functions.html),
168+
[boolean array
169+
indexing](https://data-apis.org/array-api/draft/API_specification/indexing.html#boolean-array-indexing),
170+
and the
171+
[`nonzero`](https://data-apis.org/array-api/draft/API_specification/generated/array_api.nonzero.html)
172+
function. array-api-strict currently implements all of these. In the
173+
future, [there may be a way to disable them](https://github.com/data-apis/array-api-strict/issues/7).
174+
175+
5. array-api-strict currently only supports the latest version of the array
176+
API standard. [This may change in the future depending on
177+
need](https://github.com/data-apis/array-api-strict/issues/8).
178+
179+
## Usage
180+
181+
TODO: Add a sample CI script here.
182+
183+
## Relationship to `numpy.array_api`
184+
7185
Previously this implementation was available as `numpy.array_api`, but it was
8186
moved to a separate package for NumPy 2.0.
9187

10-
Note: the history of this repo prior to commit
188+
Note that the history of this repo prior to commit
11189
fbefd42e4d11e9be20e0a4785f2619fc1aef1e7c was generated automatically
12190
from the numpy git history, using the following
13191
[git-filter-repo](https://github.com/newren/git-filter-repo) command:

0 commit comments

Comments
 (0)