Skip to content

Commit 62f4ac3

Browse files
authored
DEV: add numpydoc to pre-commit (#67)
* DEV: add numpydoc to pre-commit * update lockfile
1 parent 46df1c3 commit 62f4ac3

13 files changed

+243
-97
lines changed

.pre-commit-config.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,8 @@ repos:
7878
hooks:
7979
- id: check-dependabot
8080
- id: check-github-workflows
81+
82+
- repo: https://github.com/numpy/numpydoc
83+
rev: "v1.8.0"
84+
hooks:
85+
- id: numpydoc-validation

docs/conf.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Sphinx config."""
2+
13
import importlib.metadata
24
from typing import Any
35

pixi.lock

+174-55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+20-6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pre-commit = "*"
7373
pylint = "*"
7474
basedmypy = "*"
7575
basedpyright = "*"
76+
numpydoc = ">=1.8.0,<2"
7677
# import dependencies for mypy:
7778
array-api-strict = "*"
7879
numpy = "*"
@@ -145,13 +146,9 @@ ci-py313 = ["py313", "tests"]
145146
minversion = "6.0"
146147
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
147148
xfail_strict = true
148-
filterwarnings = [
149-
"error",
150-
]
149+
filterwarnings = ["error"]
151150
log_cli_level = "INFO"
152-
testpaths = [
153-
"tests",
154-
]
151+
testpaths = ["tests"]
155152

156153

157154
# Coverage
@@ -262,3 +259,20 @@ messages_control.disable = [
262259
"missing-function-docstring",
263260
"wrong-import-position",
264261
]
262+
263+
264+
# numpydoc
265+
266+
[tool.numpydoc_validation]
267+
checks = [
268+
"all", # report on all checks, except the below
269+
"EX01",
270+
"SA01",
271+
"ES01",
272+
]
273+
exclude = [ # don't report on objects that match any of these regex
274+
'.*test_funcs.*',
275+
'.*test_utils.*',
276+
'.*test_version.*',
277+
'.*test_vendor.*',
278+
]

src/array_api_extra/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Extra array functions built on top of the array API standard."""
2+
13
from ._funcs import atleast_nd, cov, create_diagonal, expand_dims, kron, setdiff1d, sinc
24

35
__version__ = "0.4.1.dev0"

src/array_api_extra/_funcs.py

+20-25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Public API Functions."""
2+
13
import warnings
24

35
from ._lib import _compat, _utils
@@ -22,14 +24,15 @@ def atleast_nd(x: Array, /, *, ndim: int, xp: ModuleType | None = None) -> Array
2224
Parameters
2325
----------
2426
x : array
27+
Input array.
2528
ndim : int
2629
The minimum number of dimensions for the result.
2730
xp : array_namespace, optional
28-
The standard-compatible namespace for `x`. Default: infer
31+
The standard-compatible namespace for `x`. Default: infer.
2932
3033
Returns
3134
-------
32-
res : array
35+
array
3336
An array with ``res.ndim`` >= `ndim`.
3437
If ``x.ndim`` >= `ndim`, `x` is returned.
3538
If ``x.ndim`` < `ndim`, `x` is expanded by prepending new axes
@@ -47,7 +50,6 @@ def atleast_nd(x: Array, /, *, ndim: int, xp: ModuleType | None = None) -> Array
4750
... [3, 4]]])
4851
>>> xpx.atleast_nd(x, ndim=1, xp=xp) is x
4952
True
50-
5153
"""
5254
if xp is None:
5355
xp = array_namespace(x)
@@ -77,11 +79,11 @@ def cov(m: Array, /, *, xp: ModuleType | None = None) -> Array:
7779
Each row of `m` represents a variable, and each column a single
7880
observation of all those variables.
7981
xp : array_namespace, optional
80-
The standard-compatible namespace for `m`. Default: infer
82+
The standard-compatible namespace for `m`. Default: infer.
8183
8284
Returns
8385
-------
84-
res : array
86+
array
8587
The covariance matrix of the variables.
8688
8789
Examples
@@ -104,7 +106,6 @@ def cov(m: Array, /, *, xp: ModuleType | None = None) -> Array:
104106
Array([[ 1., -1.],
105107
[-1., 1.]], dtype=array_api_strict.float64)
106108
107-
108109
Note that element :math:`C_{0,1}`, which shows the correlation between
109110
:math:`x_0` and :math:`x_1`, is negative.
110111
@@ -122,7 +123,6 @@ def cov(m: Array, /, *, xp: ModuleType | None = None) -> Array:
122123
123124
>>> xpx.cov(y, xp=xp)
124125
Array(2.14413333, dtype=array_api_strict.float64)
125-
126126
"""
127127
if xp is None:
128128
xp = array_namespace(m)
@@ -161,17 +161,17 @@ def create_diagonal(
161161
Parameters
162162
----------
163163
x : array
164-
A 1-D array
164+
A 1-D array.
165165
offset : int, optional
166166
Offset from the leading diagonal (default is ``0``).
167167
Use positive ints for diagonals above the leading diagonal,
168168
and negative ints for diagonals below the leading diagonal.
169169
xp : array_namespace, optional
170-
The standard-compatible namespace for `x`. Default: infer
170+
The standard-compatible namespace for `x`. Default: infer.
171171
172172
Returns
173173
-------
174-
res : array
174+
array
175175
A 2-D array with `x` on the diagonal (offset by `offset`).
176176
177177
Examples
@@ -191,7 +191,6 @@ def create_diagonal(
191191
[2, 0, 0, 0, 0],
192192
[0, 4, 0, 0, 0],
193193
[0, 0, 8, 0, 0]], dtype=array_api_strict.int64)
194-
195194
"""
196195
if xp is None:
197196
xp = array_namespace(x)
@@ -221,18 +220,19 @@ def expand_dims(
221220
Parameters
222221
----------
223222
a : array
223+
Array to have its shape expanded.
224224
axis : int or tuple of ints, optional
225225
Position(s) in the expanded axes where the new axis (or axes) is/are placed.
226226
If multiple positions are provided, they should be unique (note that a position
227227
given by a positive index could also be referred to by a negative index -
228228
that will also result in an error).
229229
Default: ``(0,)``.
230230
xp : array_namespace, optional
231-
The standard-compatible namespace for `a`. Default: infer
231+
The standard-compatible namespace for `a`. Default: infer.
232232
233233
Returns
234234
-------
235-
res : array
235+
array
236236
`a` with an expanded shape.
237237
238238
Examples
@@ -270,7 +270,6 @@ def expand_dims(
270270
>>> y
271271
Array([[[1],
272272
[2]]], dtype=array_api_strict.int64)
273-
274273
"""
275274
if xp is None:
276275
xp = array_namespace(a)
@@ -304,12 +303,13 @@ def kron(a: Array, b: Array, /, *, xp: ModuleType | None = None) -> Array:
304303
Parameters
305304
----------
306305
a, b : array
306+
Input arrays.
307307
xp : array_namespace, optional
308-
The standard-compatible namespace for `a` and `b`. Default: infer
308+
The standard-compatible namespace for `a` and `b`. Default: infer.
309309
310310
Returns
311311
-------
312-
res : array
312+
array
313313
The Kronecker product of `a` and `b`.
314314
315315
Notes
@@ -333,7 +333,6 @@ def kron(a: Array, b: Array, /, *, xp: ModuleType | None = None) -> Array:
333333
[ ... ... ],
334334
[ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]]
335335
336-
337336
Examples
338337
--------
339338
>>> import array_api_strict as xp
@@ -352,7 +351,6 @@ def kron(a: Array, b: Array, /, *, xp: ModuleType | None = None) -> Array:
352351
[0., 0., 1., 1.],
353352
[0., 0., 1., 1.]], dtype=array_api_strict.float64)
354353
355-
356354
>>> a = xp.reshape(xp.arange(100), (2, 5, 2, 5))
357355
>>> b = xp.reshape(xp.arange(24), (2, 3, 4))
358356
>>> c = xpx.kron(a, b, xp=xp)
@@ -365,7 +363,6 @@ def kron(a: Array, b: Array, /, *, xp: ModuleType | None = None) -> Array:
365363
>>> K = tuple(xp.asarray(I) * xp.asarray(S1) + xp.asarray(J1))
366364
>>> c[K] == a[I]*b[J]
367365
Array(True, dtype=array_api_strict.bool)
368-
369366
"""
370367
if xp is None:
371368
xp = array_namespace(a, b)
@@ -424,11 +421,11 @@ def setdiff1d(
424421
If ``True``, the input arrays are both assumed to be unique, which
425422
can speed up the calculation. Default is ``False``.
426423
xp : array_namespace, optional
427-
The standard-compatible namespace for `x1` and `x2`. Default: infer
424+
The standard-compatible namespace for `x1` and `x2`. Default: infer.
428425
429426
Returns
430427
-------
431-
res : array
428+
array
432429
1D array of values in `x1` that are not in `x2`. The result
433430
is sorted when `assume_unique` is ``False``, but otherwise only sorted
434431
if the input is sorted.
@@ -442,7 +439,6 @@ def setdiff1d(
442439
>>> x2 = xp.asarray([3, 4, 5, 6])
443440
>>> xpx.setdiff1d(x1, x2, xp=xp)
444441
Array([1, 2], dtype=array_api_strict.int64)
445-
446442
"""
447443
if xp is None:
448444
xp = array_namespace(x1, x2)
@@ -476,11 +472,11 @@ def sinc(x: Array, /, *, xp: ModuleType | None = None) -> Array:
476472
Array (possibly multi-dimensional) of values for which to calculate
477473
``sinc(x)``. Must have a real floating point dtype.
478474
xp : array_namespace, optional
479-
The standard-compatible namespace for `x`. Default: infer
475+
The standard-compatible namespace for `x`. Default: infer.
480476
481477
Returns
482478
-------
483-
res : array
479+
array
484480
``sinc(x)`` calculated elementwise, which has the same shape as the input.
485481
486482
Notes
@@ -528,7 +524,6 @@ def sinc(x: Array, /, *, xp: ModuleType | None = None) -> Array:
528524
-5.84680802e-02, -8.90384387e-02,
529525
-8.40918587e-02, -4.92362781e-02,
530526
-3.89817183e-17], dtype=array_api_strict.float64)
531-
532527
"""
533528
if xp is None:
534529
xp = array_namespace(x)

src/array_api_extra/_lib/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Modules housing private functions."""

src/array_api_extra/_lib/_compat.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""Acquire helpers from array-api-compat."""
12
# Allow packages that vendor both `array-api-extra` and
23
# `array-api-compat` to override the import location
34

src/array_api_extra/_lib/_compat.pyi

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
"""Static type stubs for `_compat.py`."""
2+
13
from types import ModuleType
24

35
from ._typing import Array, Device
46

57
# pylint: disable=missing-class-docstring,unused-argument
68

7-
class ArrayModule(ModuleType):
8-
def device(self, x: Array, /) -> Device: ...
9+
class ArrayModule(ModuleType): # numpydoc ignore=GL08
10+
def device(self, x: Array, /) -> Device: ... # numpydoc ignore=GL08
911

1012
def array_namespace(
1113
*xs: Array,
1214
api_version: str | None = None,
1315
use_compat: bool | None = None,
14-
) -> ArrayModule: ...
15-
def device(x: Array, /) -> Device: ...
16+
) -> ArrayModule: ... # numpydoc ignore=GL08
17+
def device(x: Array, /) -> Device: ... # numpydoc ignore=GL08

src/array_api_extra/_lib/_typing.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Static typing helpers."""
2+
13
from types import ModuleType
24
from typing import Any
35

src/array_api_extra/_lib/_utils.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Utility functions used by `array_api_extra/_funcs.py`."""
2+
13
from . import _compat
24
from ._typing import Array, ModuleType
35

@@ -12,9 +14,9 @@ def in1d(
1214
assume_unique: bool = False,
1315
invert: bool = False,
1416
xp: ModuleType | None = None,
15-
) -> Array:
16-
"""Checks whether each element of an array is also present in a
17-
second array.
17+
) -> Array: # numpydoc ignore=PR01,RT01
18+
"""
19+
Check whether each element of an array is also present in a second array.
1820
1921
Returns a boolean array the same length as `x1` that is True
2022
where an element of `x1` is in `x2` and False otherwise.
@@ -68,7 +70,7 @@ def mean(
6870
axis: int | tuple[int, ...] | None = None,
6971
keepdims: bool = False,
7072
xp: ModuleType | None = None,
71-
) -> Array:
73+
) -> Array: # numpydoc ignore=PR01,RT01
7274
"""
7375
Complex mean, https://github.com/data-apis/array-api/issues/846.
7476
"""

vendor_tests/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# Allow for relative imports in test_vendor.py
1+
"""Allow for relative imports in `test_vendor.py`."""
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# This file is a hook imported by src/array_api_extra/_lib/_compat.py
1+
"""This file is a hook imported by `src/array_api_extra/_lib/_compat.py`."""
2+
23
from .array_api_compat import * # noqa: F403
34
from .array_api_compat import array_namespace as array_namespace_compat
45

56

67
# Let unit tests check with `is` that we are picking up the function from this module
78
# and not from the original array_api_compat module.
8-
def array_namespace(*xs, **kwargs):
9+
def array_namespace(*xs, **kwargs): # numpydoc ignore=GL08
910
return array_namespace_compat(*xs, **kwargs)

0 commit comments

Comments
 (0)