|
1 | 1 | # Implementation Notes
|
2 | 2 |
|
3 |
| -This page outlines some notes on the implementation of array-api-compat. These |
4 |
| -details are not important for users of the package, but they may be useful to |
5 |
| -contributors. |
6 |
| - |
7 |
| -## Special Considerations |
8 |
| - |
9 |
| -array-api-compat requires some special development considerations that are |
10 |
| -different from most other Python libraries. The goal of array-api-compat is to |
11 |
| -be a small library that packages can either vendor or add as a dependency to |
12 |
| -implement array API support. Consequently, certain design considerations |
13 |
| -should be taken into account: |
14 |
| - |
15 |
| -- *No Hard Dependencies.* Although array-api-compat "depends" on NumPy, CuPy, |
16 |
| - PyTorch, etc., it does not hard depend on them. These libraries are not |
17 |
| - imported unless either an array object is passed to |
18 |
| - {func}`~.array_namespace()`, or the specific `array_api_compat.<namespace>` |
19 |
| - sub-namespace is explicitly imported. |
20 |
| - |
21 |
| -- *Vendorability.* array-api-compat should be [vendorable](vendoring). This |
22 |
| - means that, for instance, all imports in the library are relative imports. |
23 |
| - No code in the package specifically references the name `array_api_compat` |
24 |
| - (we also support renaming the package to something else). |
25 |
| - Vendorability support is tested in `tests/test_vendoring.py`. |
26 |
| - |
27 |
| -- *Pure Python.* To make array-api-compat as easy as possible to add as a |
28 |
| - dependency, the code is all pure Python. |
29 |
| - |
30 |
| -- *Minimal Wrapping Only.* The wrapping functionality is minimal. This means |
31 |
| - that if something is difficult to wrap using pure Python, or if trying to |
32 |
| - support some array API behavior would require a significant amount of code, |
33 |
| - we prefer to leave the behavior as an upstream issue for the array library, |
34 |
| - and [document it as a known difference](../supported-array-libraries.md). |
35 |
| - |
36 |
| - This also means that we do not at this point in time implement anything |
37 |
| - other than wrappers for functions in the standard, and basic [helper |
38 |
| - functions](../helper-functions.rst) that would be useful for most users of |
39 |
| - array-api-compat. The addition of functions that are not part of the array |
40 |
| - API standard is currently out-of-scope for this package (see the |
41 |
| - [Scope](scope) section of the documentation). |
42 |
| - |
43 |
| -- *No Side-Effects*. array-api-compat behavior should be localized to only the |
44 |
| - specific code that imports and uses it. It should be invisible to end-users |
45 |
| - or users of dependent codes. This in particular implies to the next two |
46 |
| - points. |
47 |
| - |
48 |
| -- *No Monkey Patching.* `array-api-compat` should not attempt to modify |
49 |
| - anything about the underlying library. It is a *wrapper* library only. |
50 |
| - |
51 |
| -- *No Modifying the Array Object.* The array (or tensor) object of the array |
52 |
| - library cannot be modified. This also precludes the creation of array |
53 |
| - subclasses or wrapper classes. |
54 |
| - |
55 |
| - Any non-standard behavior that is built-in to the array object, such as the |
56 |
| - behavior of [array |
57 |
| - methods](https://data-apis.org/array-api/latest/API_specification/array_object.html), |
58 |
| - is therefore left unwrapped. Users can workaround issues by using |
59 |
| - corresponding [elementwise |
60 |
| - functions](https://data-apis.org/array-api/latest/API_specification/elementwise_functions.html) |
61 |
| - instead of |
62 |
| - [operators](https://data-apis.org/array-api/latest/API_specification/array_object.html#operators), |
63 |
| - and by using the [helper functions](../helper-functions.rst) provided by |
64 |
| - array-api-compat instead of attributes or methods like `x.to_device()`. |
65 |
| - |
66 |
| -- *Avoid Restricting Behavior that is Outside the Scope of the Standard.* All |
67 |
| - array libraries have functions and behaviors that are outside of the scope |
68 |
| - of what is specified by the standard. These behaviors should be left intact |
69 |
| - whenever possible, unless the standard explicitly disallows something. This |
70 |
| - means |
71 |
| - |
72 |
| - - All namespaces are *extended* with wrapper functions. You may notice the |
73 |
| - extensive use of `import *` in various files in `array_api_compat`. While |
74 |
| - this would normally be questionable, this is the [one actual legitimate |
75 |
| - use-case for `import *`](https://peps.python.org/pep-0008/#imports), to |
76 |
| - re-export names from an external namespace. |
77 |
| - |
78 |
| - - All wrapper functions pass `**kwargs` through to the wrapped function. |
79 |
| - |
80 |
| - - Input types not supported by the standard should work if they work in the |
81 |
| - underlying wrapped function (for instance, Python scalars or `np.ndarray` |
82 |
| - subclasses). |
83 |
| - |
84 |
| - By keeping underlying behaviors intact, it is easier for libraries to swap |
85 |
| - out NumPy or other array libraries for array-api-compat, and it is easier |
86 |
| - for libraries to write array library-specific code paths. |
87 |
| - |
88 |
| - The onus is on users of array-api-compat to ensure their array API code is |
89 |
| - portable, e.g., by testing against [array-api-strict](array-api-strict). |
90 |
| - |
91 |
| - |
92 |
| -## Avoiding Code Duplication |
93 |
| - |
94 | 3 | Since NumPy, CuPy, and to a degree, Dask, are nearly identical in behavior,
|
95 | 4 | most wrapping logic can be shared between them. Wrapped functions that have
|
96 | 5 | the same logic between multiple libraries are in `array_api_compat/common/`.
|
@@ -138,33 +47,3 @@ identical PyTorch uses a similar layout in `array_api_compat/torch/`, but it
|
138 | 47 | differs enough from NumPy/CuPy that very few common wrappers for those
|
139 | 48 | libraries are reused. Dask is close to NumPy in behavior and so most Dask
|
140 | 49 | functions also reuse the NumPy/CuPy common wrappers.
|
141 |
| - |
142 |
| -## Tests |
143 |
| - |
144 |
| -The majority of the behavior for array-api-compat is tested by the |
145 |
| -[array-api-tests](https://github.com/data-apis/array-api-tests) test suite for |
146 |
| -the array API standard. There are also array-api-compat specific tests in |
147 |
| -[`tests/`](https://github.com/data-apis/array-api-compat/tree/main/tests). |
148 |
| -These tests should be limited to things that are not tested by the test suite, |
149 |
| -e.g., tests for [helper functions](../helper-functions.rst) or for behavior |
150 |
| -that is not strictly required by the standard. |
151 |
| - |
152 |
| -array-api-tests is run against all supported libraries are tested on CI |
153 |
| -([except for JAX](jax-support)). This is achieved by a [reusable GitHub Actions |
154 |
| -Workflow](https://github.com/data-apis/array-api-compat/blob/main/.github/workflows/array-api-tests.yml). |
155 |
| -Most libraries have tests that must be xfailed or skipped for various reasons. |
156 |
| -These are defined in specific `<library>-xfails.txt` files and are |
157 |
| -automatically forwarded to array-api-tests. |
158 |
| - |
159 |
| -You may often need to update these xfail files, either to add new xfails |
160 |
| -(e.g., because of new test suite features, or because a test that was |
161 |
| -previously thought to be passing actually flaky fails). Try to keep the xfails |
162 |
| -files organized, with comments pointing to upstream issues whenever possible. |
163 |
| - |
164 |
| -From time to time, xpass tests should be removed from the xfail files, but be |
165 |
| -aware that many xfail tests are flaky, so an xpass should only be removed if |
166 |
| -you know that the underlying issue has been fixed. |
167 |
| - |
168 |
| -Array libraries that require a GPU to run (currently only CuPy) cannot be |
169 |
| -tested on CI. There is a helper script `test_cupy.sh` that can be used to |
170 |
| -manually test CuPy on a machine with a CUDA GPU. |
0 commit comments