array-api-shape-check 0.1.3__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {array_api_shape_check-0.1.3/src/array_api_shape_check.egg-info → array_api_shape_check-1.0.1}/PKG-INFO +2 -2
- array_api_shape_check-1.0.1/pyproject.toml +67 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/_main.py +56 -34
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1/src/array_api_shape_check.egg-info}/PKG-INFO +2 -2
- array_api_shape_check-1.0.1/tests/test_main.py +43 -0
- array_api_shape_check-0.1.3/pyproject.toml +0 -149
- array_api_shape_check-0.1.3/tests/test_main.py +0 -11
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/LICENSE +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/README.md +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/setup.cfg +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/__init__.py +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/py.typed +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check.egg-info/SOURCES.txt +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check.egg-info/dependency_links.txt +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check.egg-info/requires.txt +0 -0
- {array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: array-api-shape-check
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Check shapes of input arrays easily
|
|
5
|
-
Author
|
|
5
|
+
Author: 34j
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/34j/array-api-shape-check/issues
|
|
8
8
|
Project-URL: Changelog, https://github.com/34j/array-api-shape-check/blob/main/CHANGELOG.md
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "setuptools.build_meta"
|
|
3
|
+
requires = [ "setuptools>=77.0.3" ]
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "array-api-shape-check"
|
|
7
|
+
version = "1.0.1"
|
|
8
|
+
description = "Check shapes of input arrays easily"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "34j" },
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.12"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Natural Language :: English",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Software Development :: Libraries",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"attrs>=26.1",
|
|
28
|
+
"more-itertools>=11.0.2",
|
|
29
|
+
"numpy>=2.4.4",
|
|
30
|
+
"types-array-api>=1.1.4",
|
|
31
|
+
]
|
|
32
|
+
urls."Bug Tracker" = "https://github.com/34j/array-api-shape-check/issues"
|
|
33
|
+
urls.Changelog = "https://github.com/34j/array-api-shape-check/blob/main/CHANGELOG.md"
|
|
34
|
+
urls.documentation = "https://array-api-shape-check.readthedocs.io"
|
|
35
|
+
urls.repository = "https://github.com/34j/array-api-shape-check"
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"coverage",
|
|
40
|
+
"packaging-34j[test]",
|
|
41
|
+
"pytest",
|
|
42
|
+
"pytest-cov",
|
|
43
|
+
"ty",
|
|
44
|
+
]
|
|
45
|
+
docs = [
|
|
46
|
+
"packaging-34j[docs]",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
extend = ".venv/ruff.toml"
|
|
51
|
+
|
|
52
|
+
[tool.pyproject-fmt]
|
|
53
|
+
max_supported_python = "3.14"
|
|
54
|
+
|
|
55
|
+
[tool.ty]
|
|
56
|
+
terminal.error-on-warning = true
|
|
57
|
+
|
|
58
|
+
[tool.pytest]
|
|
59
|
+
addopts = [
|
|
60
|
+
"-v",
|
|
61
|
+
"-Wonce",
|
|
62
|
+
"-p no:doctest",
|
|
63
|
+
"--cov=array_api_shape_check",
|
|
64
|
+
"--cov-report=term",
|
|
65
|
+
"--cov-report=xml",
|
|
66
|
+
]
|
|
67
|
+
pythonpath = [ "src" ]
|
{array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/_main.py
RENAMED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import inspect
|
|
1
2
|
import re
|
|
2
3
|
from collections import defaultdict
|
|
3
4
|
from collections.abc import Sequence
|
|
4
5
|
from itertools import groupby
|
|
5
|
-
from typing import Any
|
|
6
|
+
from typing import Any, cast
|
|
6
7
|
|
|
7
8
|
import attrs
|
|
8
9
|
import numpy as np
|
|
@@ -34,43 +35,50 @@ class SubscriptInfoFromShapeItemUnchecked(SubscriptInfoFromSubcriptItem):
|
|
|
34
35
|
def __repr__(self) -> str:
|
|
35
36
|
if self.is_variable:
|
|
36
37
|
return f"*{self.name}:{self.shape_current}"
|
|
37
|
-
|
|
38
|
-
return f"{self.name}:{self.shape_current[0]}"
|
|
38
|
+
return f"{self.name}:{self.shape_current[0]}"
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
@attrs.frozen(kw_only=True)
|
|
42
|
-
class SubscriptInfoFromShapeItemUnique(
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
class SubscriptInfoFromShapeItemUnique[BroadcastShape: tuple[int, ...] | None](
|
|
43
|
+
SubscriptInfoFromSubcriptItem
|
|
44
|
+
):
|
|
45
|
+
shape_broadcasted: BroadcastShape
|
|
46
|
+
"""The broadcast shape, or None for an inconsistent subscript."""
|
|
45
47
|
|
|
46
48
|
def __repr__(self) -> str:
|
|
47
49
|
if self.is_variable:
|
|
48
50
|
return f"*{self.name}:{self.shape_broadcasted}"
|
|
49
|
-
|
|
50
|
-
return f"{self.name}:
|
|
51
|
+
if self.shape_broadcasted is None:
|
|
52
|
+
return f"{self.name}:None"
|
|
53
|
+
return f"{self.name}:{cast('tuple[int, ...]', self.shape_broadcasted)[0]}"
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
@attrs.frozen(kw_only=True)
|
|
54
|
-
class SubscriptInfoFromShapeItem(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
class SubscriptInfoFromShapeItem[BroadcastShape: tuple[int, ...] | None](
|
|
58
|
+
SubscriptInfoFromShapeItemUnchecked
|
|
59
|
+
):
|
|
60
|
+
shape_broadcasted: BroadcastShape
|
|
61
|
+
"""The broadcast shape, or None for an inconsistent subscript."""
|
|
57
62
|
|
|
58
63
|
def __repr__(self) -> str:
|
|
64
|
+
if self.shape_broadcasted is None:
|
|
65
|
+
current = self.shape_current if self.is_variable else self.shape_current[0]
|
|
66
|
+
return f"{'*' if self.is_variable else ''}{self.name}:{current}->None"
|
|
59
67
|
if self.is_variable:
|
|
60
68
|
if self.shape_current != self.shape_broadcasted:
|
|
61
69
|
return f"*{self.name}:{self.shape_current}->{self.shape_broadcasted}"
|
|
62
70
|
return f"*{self.name}:{self.shape_current}"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
if self.shape_current != self.shape_broadcasted:
|
|
72
|
+
broadcasted = cast("tuple[int, ...]", self.shape_broadcasted)
|
|
73
|
+
return f"{self.name}:{self.shape_current[0]}->{broadcasted[0]}"
|
|
74
|
+
return f"{self.name}:{self.shape_current[0]}"
|
|
67
75
|
|
|
68
76
|
|
|
69
77
|
@attrs.frozen(kw_only=True)
|
|
70
|
-
class SubscriptInfoFromShape:
|
|
71
|
-
all: tuple[tuple[SubscriptInfoFromShapeItem, ...], ...]
|
|
78
|
+
class SubscriptInfoFromShape[BroadcastShape: tuple[int, ...] | None]:
|
|
79
|
+
all: tuple[tuple[SubscriptInfoFromShapeItem[BroadcastShape], ...], ...]
|
|
72
80
|
"""The subscript info grouped by order, then by operand"""
|
|
73
|
-
unique: dict[str, SubscriptInfoFromShapeItemUnique]
|
|
81
|
+
unique: dict[str, SubscriptInfoFromShapeItemUnique[BroadcastShape]]
|
|
74
82
|
"""The unique subscripts,
|
|
75
83
|
ignoring order and shapes not broadcasted,
|
|
76
84
|
sorted lexicographically by name"""
|
|
@@ -82,7 +90,7 @@ class InconsistentNdimError(ValueError):
|
|
|
82
90
|
reason: str
|
|
83
91
|
|
|
84
92
|
|
|
85
|
-
class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
|
|
93
|
+
class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError): # noqa: N818
|
|
86
94
|
def __init__(
|
|
87
95
|
self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
|
|
88
96
|
) -> None:
|
|
@@ -97,7 +105,7 @@ class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
|
|
|
97
105
|
)
|
|
98
106
|
|
|
99
107
|
|
|
100
|
-
class InconsistentNdimErrorNoSolutions(InconsistentNdimError):
|
|
108
|
+
class InconsistentNdimErrorNoSolutions(InconsistentNdimError): # noqa: N818
|
|
101
109
|
def __init__(
|
|
102
110
|
self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
|
|
103
111
|
) -> None:
|
|
@@ -113,16 +121,19 @@ class InconsistentNdimErrorNoSolutions(InconsistentNdimError):
|
|
|
113
121
|
|
|
114
122
|
|
|
115
123
|
class InconsistentShapeError(ValueError):
|
|
116
|
-
subscript_info: SubscriptInfoFromShape
|
|
124
|
+
subscript_info: SubscriptInfoFromShape[tuple[int, ...] | None]
|
|
117
125
|
|
|
118
|
-
def __init__(
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
subscript_info: SubscriptInfoFromShape[tuple[int, ...] | None],
|
|
129
|
+
reason: str,
|
|
130
|
+
*args: object,
|
|
131
|
+
) -> None:
|
|
119
132
|
super().__init__("Inconsistent shapes: " + str(subscript_info.all) + f"\n {reason}", *args)
|
|
120
133
|
self.subscript_info = subscript_info
|
|
121
134
|
|
|
122
135
|
|
|
123
136
|
def _get_operand_names(*operands: Any) -> list[str | None]:
|
|
124
|
-
import inspect
|
|
125
|
-
|
|
126
137
|
frame = inspect.currentframe()
|
|
127
138
|
if frame is None:
|
|
128
139
|
return [None] * len(operands)
|
|
@@ -236,6 +247,10 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
|
|
|
236
247
|
------
|
|
237
248
|
ValueError
|
|
238
249
|
If the subscript is invalid.
|
|
250
|
+
InconsistentNdimErrorMultipleSolutions
|
|
251
|
+
If the variable dimensions cannot be uniquely determined.
|
|
252
|
+
InconsistentNdimErrorNoSolutions
|
|
253
|
+
If the variable dimensions have no valid solution.
|
|
239
254
|
|
|
240
255
|
Examples
|
|
241
256
|
--------
|
|
@@ -306,18 +321,19 @@ def _parse_shapes(
|
|
|
306
321
|
)
|
|
307
322
|
shapes: tuple[tuple[int, ...], ...] = ()
|
|
308
323
|
for operand in operands:
|
|
309
|
-
shape: tuple[int, ...] # type: ignore
|
|
310
324
|
if isinstance(operand, tuple):
|
|
311
|
-
|
|
325
|
+
if None in operand:
|
|
326
|
+
raise ValueError("Operand shape cannot contain None")
|
|
327
|
+
shape = cast("tuple[int, ...]", operand)
|
|
312
328
|
elif hasattr(operand, "shape"):
|
|
313
329
|
if None in operand.shape:
|
|
314
330
|
raise ValueError("Operand shape cannot contain None")
|
|
315
|
-
shape = operand.shape
|
|
331
|
+
shape = cast("tuple[int, ...]", operand.shape)
|
|
316
332
|
else:
|
|
317
333
|
raise TypeError(
|
|
318
334
|
f"Invalid operand: expected an array or a shape tuple, but got {type(operand)}"
|
|
319
335
|
)
|
|
320
|
-
shapes += (shape,)
|
|
336
|
+
shapes += (shape,)
|
|
321
337
|
del operands
|
|
322
338
|
ndims = [len(shape) for shape in shapes]
|
|
323
339
|
try:
|
|
@@ -336,14 +352,14 @@ def _parse_shapes(
|
|
|
336
352
|
shape_current=shape[: name_to_ndim[item.name]],
|
|
337
353
|
),
|
|
338
354
|
)
|
|
339
|
-
shape = shape[name_to_ndim[item.name] :]
|
|
355
|
+
shape = shape[name_to_ndim[item.name] :] # noqa: PLW2901
|
|
340
356
|
info_all += (info_array_new,)
|
|
341
357
|
return info_all
|
|
342
358
|
|
|
343
359
|
|
|
344
360
|
def check_shapes(
|
|
345
361
|
subscripts: str, /, *operands: Array | tuple[int | None, ...], names: str | None = None
|
|
346
|
-
) -> SubscriptInfoFromShape:
|
|
362
|
+
) -> SubscriptInfoFromShape[tuple[int, ...]]:
|
|
347
363
|
"""
|
|
348
364
|
Parse variable subscript ndims by solving linear equations.
|
|
349
365
|
|
|
@@ -373,6 +389,8 @@ def check_shapes(
|
|
|
373
389
|
------
|
|
374
390
|
ValueError
|
|
375
391
|
If the subscript is invalid.
|
|
392
|
+
InconsistentShapeError
|
|
393
|
+
If the operand shapes are inconsistent.
|
|
376
394
|
|
|
377
395
|
Examples
|
|
378
396
|
--------
|
|
@@ -432,12 +450,15 @@ def check_shapes(
|
|
|
432
450
|
info_flatten_keyed = [(i, item) for i, info_array in enumerate(info_all) for item in info_array]
|
|
433
451
|
errors = []
|
|
434
452
|
shape_broadcasted = {}
|
|
435
|
-
for key, group in groupby(
|
|
453
|
+
for key, group in groupby(
|
|
454
|
+
sorted(info_flatten_keyed, key=lambda x: x[1].name), key=lambda x: x[1].name
|
|
455
|
+
):
|
|
436
456
|
group_list = list(group)
|
|
437
457
|
shapes = [item.shape_current for _, item in group_list]
|
|
438
458
|
try:
|
|
439
459
|
shape_broadcasted[key] = np.broadcast_shapes(*shapes)
|
|
440
460
|
except ValueError:
|
|
461
|
+
shape_broadcasted[key] = None
|
|
441
462
|
inner_text = ", ".join([f"{shape} ({names_[i]})" for i, shape in group_list])
|
|
442
463
|
errors.append(f"Key {key}: shapes {inner_text} are not broadcastable")
|
|
443
464
|
|
|
@@ -450,7 +471,7 @@ def check_shapes(
|
|
|
450
471
|
name=item.name,
|
|
451
472
|
is_variable=item.is_variable,
|
|
452
473
|
shape_current=item.shape_current,
|
|
453
|
-
shape_broadcasted=shape_broadcasted
|
|
474
|
+
shape_broadcasted=shape_broadcasted[item.name],
|
|
454
475
|
),
|
|
455
476
|
)
|
|
456
477
|
info_all_new += (info_array_new,)
|
|
@@ -459,7 +480,7 @@ def check_shapes(
|
|
|
459
480
|
SubscriptInfoFromShapeItemUnique(
|
|
460
481
|
name=item.name,
|
|
461
482
|
is_variable=item.is_variable,
|
|
462
|
-
shape_broadcasted=shape_broadcasted
|
|
483
|
+
shape_broadcasted=shape_broadcasted[item.name],
|
|
463
484
|
)
|
|
464
485
|
for info_array in info_all_new
|
|
465
486
|
for item in info_array
|
|
@@ -472,4 +493,5 @@ def check_shapes(
|
|
|
472
493
|
if errors:
|
|
473
494
|
raise InconsistentShapeError(result, "\n".join(errors))
|
|
474
495
|
|
|
475
|
-
|
|
496
|
+
# No broadcast shape can be None unless an inconsistency was recorded.
|
|
497
|
+
return cast("SubscriptInfoFromShape[tuple[int, ...]]", result)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: array-api-shape-check
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Check shapes of input arrays easily
|
|
5
|
-
Author
|
|
5
|
+
Author: 34j
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/34j/array-api-shape-check/issues
|
|
8
8
|
Project-URL: Changelog, https://github.com/34j/array-api-shape-check/blob/main/CHANGELOG.md
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from array_api_shape_check import InconsistentShapeError, check_shapes
|
|
4
|
+
from array_api_shape_check._main import _get_operand_names # noqa: PLC2701
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_get_operand_names():
|
|
8
|
+
def inner(a, b) -> list[str | None]:
|
|
9
|
+
return _get_operand_names(a, b)
|
|
10
|
+
|
|
11
|
+
c = 1
|
|
12
|
+
assert inner(c, 4 * 4)[0] == "c"
|
|
13
|
+
# assert inner(c, 4 * 4)[1] is not None
|
|
14
|
+
# assert "@py_assert" in repr(inner(c, 4 * 4)[1])
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.parametrize(
|
|
18
|
+
("subscripts", "shapes", "key"),
|
|
19
|
+
[
|
|
20
|
+
("i,i", ((3,), (4,)), "i"),
|
|
21
|
+
("ij,ji", ((3, 4), (4, 9)), "i"),
|
|
22
|
+
("*BM,*BN", ((2, 3), (4, 3)), "B"),
|
|
23
|
+
],
|
|
24
|
+
)
|
|
25
|
+
def test_incompatible_shapes(
|
|
26
|
+
subscripts: str, shapes: tuple[tuple[int, ...], ...], key: str
|
|
27
|
+
) -> None:
|
|
28
|
+
with pytest.raises(InconsistentShapeError, match=f"Key {key}") as exc:
|
|
29
|
+
check_shapes(subscripts, *shapes, names="first,second")
|
|
30
|
+
assert exc.value.subscript_info.unique[key].shape_broadcasted is None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_broadcasts_nonconsecutive_subscripts() -> None:
|
|
34
|
+
info = check_shapes("ij,ji", (1, 4), (4, 9), names="first,second")
|
|
35
|
+
assert info.unique["i"].shape_broadcasted == (9,)
|
|
36
|
+
assert info.unique["j"].shape_broadcasted == (4,)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_reports_all_inconsistent_subscripts() -> None:
|
|
40
|
+
with pytest.raises(InconsistentShapeError) as exc:
|
|
41
|
+
check_shapes("ij,ij", (2, 3), (4, 5), names="first,second")
|
|
42
|
+
assert "Key i" in str(exc.value)
|
|
43
|
+
assert "Key j" in str(exc.value)
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
build-backend = "setuptools.build_meta"
|
|
3
|
-
requires = [ "setuptools>=77.0.3" ]
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "array-api-shape-check"
|
|
7
|
-
version = "0.1.3"
|
|
8
|
-
description = "Check shapes of input arrays easily"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license = "MIT"
|
|
11
|
-
authors = [
|
|
12
|
-
{ name = "34j", email = "34j.95a2p@simplelogin.com" },
|
|
13
|
-
]
|
|
14
|
-
requires-python = ">=3.12"
|
|
15
|
-
classifiers = [
|
|
16
|
-
"Development Status :: 2 - Pre-Alpha",
|
|
17
|
-
"Intended Audience :: Developers",
|
|
18
|
-
"Natural Language :: English",
|
|
19
|
-
"Operating System :: OS Independent",
|
|
20
|
-
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
-
"Programming Language :: Python :: 3.12",
|
|
22
|
-
"Programming Language :: Python :: 3.13",
|
|
23
|
-
"Programming Language :: Python :: 3.14",
|
|
24
|
-
"Topic :: Software Development :: Libraries",
|
|
25
|
-
]
|
|
26
|
-
dependencies = [
|
|
27
|
-
"attrs>=26.1",
|
|
28
|
-
"more-itertools>=11.0.2",
|
|
29
|
-
"numpy>=2.4.4",
|
|
30
|
-
"types-array-api>=1.1.4",
|
|
31
|
-
]
|
|
32
|
-
urls."Bug Tracker" = "https://github.com/34j/array-api-shape-check/issues"
|
|
33
|
-
urls.Changelog = "https://github.com/34j/array-api-shape-check/blob/main/CHANGELOG.md"
|
|
34
|
-
urls.documentation = "https://array-api-shape-check.readthedocs.io"
|
|
35
|
-
urls.repository = "https://github.com/34j/array-api-shape-check"
|
|
36
|
-
|
|
37
|
-
[dependency-groups]
|
|
38
|
-
dev = [
|
|
39
|
-
"coverage",
|
|
40
|
-
"numpy>=2.4.4",
|
|
41
|
-
"pytest==9.*",
|
|
42
|
-
"pytest-cov==7.*",
|
|
43
|
-
"sybil[pytest]",
|
|
44
|
-
"ty",
|
|
45
|
-
]
|
|
46
|
-
docs = [
|
|
47
|
-
"furo; python_version>='3.12'",
|
|
48
|
-
"myst-parser; python_version>='3.12'",
|
|
49
|
-
"sphinx==9.*; python_version>='3.12'",
|
|
50
|
-
"sphinx-autobuild; python_version>='3.12'",
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
[tool.ruff]
|
|
54
|
-
line-length = 100
|
|
55
|
-
preview = true
|
|
56
|
-
format.docstring-code-format = true
|
|
57
|
-
lint.select = [
|
|
58
|
-
"B", # flake8-bugbear
|
|
59
|
-
"C4", # flake8-comprehensions
|
|
60
|
-
"D", # flake8-docstrings
|
|
61
|
-
"E", # pycodestyle
|
|
62
|
-
"F", # pyflake
|
|
63
|
-
"I", # isort
|
|
64
|
-
"RUF", # ruff specific
|
|
65
|
-
"S", # flake8-bandit
|
|
66
|
-
"UP", # pyupgrade
|
|
67
|
-
"W", # pycodestyle
|
|
68
|
-
]
|
|
69
|
-
lint.ignore = [
|
|
70
|
-
"D100", # Missing docstring in public module
|
|
71
|
-
"D104", # Missing docstring in public package
|
|
72
|
-
"D107", # Missing docstring in `__init__`
|
|
73
|
-
"D203", # 1 blank line required before class docstring
|
|
74
|
-
"D212", # Multi-line docstring summary should start at the first line
|
|
75
|
-
"D401", # First line of docstring should be in imperative mood
|
|
76
|
-
]
|
|
77
|
-
lint.per-file-ignores."conftest.py" = [ "D100" ]
|
|
78
|
-
lint.per-file-ignores."docs/conf.py" = [ "D100" ]
|
|
79
|
-
lint.per-file-ignores."setup.py" = [ "D100" ]
|
|
80
|
-
lint.per-file-ignores."tests/**/*" = [
|
|
81
|
-
"D100",
|
|
82
|
-
"D101",
|
|
83
|
-
"D102",
|
|
84
|
-
"D103",
|
|
85
|
-
"D104",
|
|
86
|
-
"S101",
|
|
87
|
-
]
|
|
88
|
-
lint.isort.known-first-party = [ "array_api_shape_check", "tests" ]
|
|
89
|
-
|
|
90
|
-
[tool.pyproject-fmt]
|
|
91
|
-
max_supported_python = "3.14"
|
|
92
|
-
|
|
93
|
-
[tool.ty]
|
|
94
|
-
terminal.error-on-warning = true
|
|
95
|
-
src.exclude = [ "docs/" ]
|
|
96
|
-
|
|
97
|
-
[tool.pytest]
|
|
98
|
-
minversion = "9.0"
|
|
99
|
-
addopts = [
|
|
100
|
-
"-v",
|
|
101
|
-
"-Wonce",
|
|
102
|
-
"-p no:doctest",
|
|
103
|
-
"--cov=array_api_shape_check",
|
|
104
|
-
"--cov-report=term",
|
|
105
|
-
"--cov-report=xml",
|
|
106
|
-
]
|
|
107
|
-
pythonpath = [ "src" ]
|
|
108
|
-
|
|
109
|
-
[tool.coverage]
|
|
110
|
-
run.branch = true
|
|
111
|
-
paths.source = [
|
|
112
|
-
"src",
|
|
113
|
-
".tox/**/site-packages",
|
|
114
|
-
]
|
|
115
|
-
report.exclude_lines = [
|
|
116
|
-
"@overload",
|
|
117
|
-
'if __name__ == "__main__":',
|
|
118
|
-
"if TYPE_CHECKING",
|
|
119
|
-
"pragma: no cover",
|
|
120
|
-
"raise NotImplementedError",
|
|
121
|
-
]
|
|
122
|
-
|
|
123
|
-
[tool.semantic_release]
|
|
124
|
-
allow_zero_version = true
|
|
125
|
-
version_toml = [ "pyproject.toml:project.version" ]
|
|
126
|
-
version_variables = [
|
|
127
|
-
"src/array_api_shape_check/__init__.py:__version__",
|
|
128
|
-
"docs/conf.py:release",
|
|
129
|
-
]
|
|
130
|
-
build_command = """
|
|
131
|
-
pip install uv
|
|
132
|
-
uv lock
|
|
133
|
-
git add uv.lock
|
|
134
|
-
uv build
|
|
135
|
-
"""
|
|
136
|
-
branches.main.match = "main"
|
|
137
|
-
branches.noop.match = "(?!main$)"
|
|
138
|
-
branches.noop.prerelease = true
|
|
139
|
-
changelog.exclude_commit_patterns = [
|
|
140
|
-
"chore(?:\\([^)]*?\\))?: .+",
|
|
141
|
-
"ci(?:\\([^)]*?\\))?: .+",
|
|
142
|
-
"refactor(?:\\([^)]*?\\))?: .+",
|
|
143
|
-
"style(?:\\([^)]*?\\))?: .+",
|
|
144
|
-
"test(?:\\([^)]*?\\))?: .+",
|
|
145
|
-
"build\\((?!deps\\): .+)",
|
|
146
|
-
"Merged? .*",
|
|
147
|
-
"Initial [Cc]ommit.*", # codespell:ignore
|
|
148
|
-
]
|
|
149
|
-
changelog.environment.keep_trailing_newline = true
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from array_api_shape_check._main import _get_operand_names
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_get_operand_names():
|
|
5
|
-
def inner(a, b) -> list[str | None]:
|
|
6
|
-
return _get_operand_names(a, b)
|
|
7
|
-
|
|
8
|
-
c = 1
|
|
9
|
-
assert inner(c, 4 * 4)[0] == "c"
|
|
10
|
-
# assert inner(c, 4 * 4)[1] is not None
|
|
11
|
-
# assert "@py_assert" in repr(inner(c, 4 * 4)[1])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/__init__.py
RENAMED
|
File without changes
|
{array_api_shape_check-0.1.3 → array_api_shape_check-1.0.1}/src/array_api_shape_check/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|