array-api-shape-check 0.1.3__tar.gz → 1.0.0__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.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: array-api-shape-check
3
- Version: 0.1.3
3
+ Version: 1.0.0
4
4
  Summary: Check shapes of input arrays easily
5
- Author-email: 34j <34j.95a2p@simplelogin.com>
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.0"
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" ]
@@ -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,8 +35,7 @@ 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
- else:
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)
@@ -46,8 +46,7 @@ class SubscriptInfoFromShapeItemUnique(SubscriptInfoFromSubcriptItem):
46
46
  def __repr__(self) -> str:
47
47
  if self.is_variable:
48
48
  return f"*{self.name}:{self.shape_broadcasted}"
49
- else:
50
- return f"{self.name}:{self.shape_broadcasted[0]}"
49
+ return f"{self.name}:{self.shape_broadcasted[0]}"
51
50
 
52
51
 
53
52
  @attrs.frozen(kw_only=True)
@@ -60,10 +59,9 @@ class SubscriptInfoFromShapeItem(SubscriptInfoFromShapeItemUnchecked):
60
59
  if self.shape_current != self.shape_broadcasted:
61
60
  return f"*{self.name}:{self.shape_current}->{self.shape_broadcasted}"
62
61
  return f"*{self.name}:{self.shape_current}"
63
- else:
64
- if self.shape_current != self.shape_broadcasted:
65
- return f"{self.name}:{self.shape_current[0]}->{self.shape_broadcasted[0]}"
66
- return f"{self.name}:{self.shape_current[0]}"
62
+ if self.shape_current != self.shape_broadcasted:
63
+ return f"{self.name}:{self.shape_current[0]}->{self.shape_broadcasted[0]}"
64
+ return f"{self.name}:{self.shape_current[0]}"
67
65
 
68
66
 
69
67
  @attrs.frozen(kw_only=True)
@@ -82,7 +80,7 @@ class InconsistentNdimError(ValueError):
82
80
  reason: str
83
81
 
84
82
 
85
- class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
83
+ class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError): # noqa: N818
86
84
  def __init__(
87
85
  self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
88
86
  ) -> None:
@@ -97,7 +95,7 @@ class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
97
95
  )
98
96
 
99
97
 
100
- class InconsistentNdimErrorNoSolutions(InconsistentNdimError):
98
+ class InconsistentNdimErrorNoSolutions(InconsistentNdimError): # noqa: N818
101
99
  def __init__(
102
100
  self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
103
101
  ) -> None:
@@ -121,8 +119,6 @@ class InconsistentShapeError(ValueError):
121
119
 
122
120
 
123
121
  def _get_operand_names(*operands: Any) -> list[str | None]:
124
- import inspect
125
-
126
122
  frame = inspect.currentframe()
127
123
  if frame is None:
128
124
  return [None] * len(operands)
@@ -236,6 +232,10 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
236
232
  ------
237
233
  ValueError
238
234
  If the subscript is invalid.
235
+ InconsistentNdimErrorMultipleSolutions
236
+ If the variable dimensions cannot be uniquely determined.
237
+ InconsistentNdimErrorNoSolutions
238
+ If the variable dimensions have no valid solution.
239
239
 
240
240
  Examples
241
241
  --------
@@ -306,18 +306,19 @@ def _parse_shapes(
306
306
  )
307
307
  shapes: tuple[tuple[int, ...], ...] = ()
308
308
  for operand in operands:
309
- shape: tuple[int, ...] # type: ignore
310
309
  if isinstance(operand, tuple):
311
- shape = operand
310
+ if None in operand:
311
+ raise ValueError("Operand shape cannot contain None")
312
+ shape = cast("tuple[int, ...]", operand)
312
313
  elif hasattr(operand, "shape"):
313
314
  if None in operand.shape:
314
315
  raise ValueError("Operand shape cannot contain None")
315
- shape = operand.shape
316
+ shape = cast("tuple[int, ...]", operand.shape)
316
317
  else:
317
318
  raise TypeError(
318
319
  f"Invalid operand: expected an array or a shape tuple, but got {type(operand)}"
319
320
  )
320
- shapes += (shape,) # type: ignore
321
+ shapes += (shape,)
321
322
  del operands
322
323
  ndims = [len(shape) for shape in shapes]
323
324
  try:
@@ -336,7 +337,7 @@ def _parse_shapes(
336
337
  shape_current=shape[: name_to_ndim[item.name]],
337
338
  ),
338
339
  )
339
- shape = shape[name_to_ndim[item.name] :]
340
+ shape = shape[name_to_ndim[item.name] :] # noqa: PLW2901
340
341
  info_all += (info_array_new,)
341
342
  return info_all
342
343
 
@@ -373,6 +374,8 @@ def check_shapes(
373
374
  ------
374
375
  ValueError
375
376
  If the subscript is invalid.
377
+ InconsistentShapeError
378
+ If the operand shapes are inconsistent.
376
379
 
377
380
  Examples
378
381
  --------
@@ -450,7 +453,7 @@ def check_shapes(
450
453
  name=item.name,
451
454
  is_variable=item.is_variable,
452
455
  shape_current=item.shape_current,
453
- shape_broadcasted=shape_broadcasted.get(item.name), # type: ignore
456
+ shape_broadcasted=shape_broadcasted[item.name],
454
457
  ),
455
458
  )
456
459
  info_all_new += (info_array_new,)
@@ -459,7 +462,7 @@ def check_shapes(
459
462
  SubscriptInfoFromShapeItemUnique(
460
463
  name=item.name,
461
464
  is_variable=item.is_variable,
462
- shape_broadcasted=shape_broadcasted.get(item.name), # type: ignore
465
+ shape_broadcasted=shape_broadcasted[item.name],
463
466
  )
464
467
  for info_array in info_all_new
465
468
  for item in info_array
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: array-api-shape-check
3
- Version: 0.1.3
3
+ Version: 1.0.0
4
4
  Summary: Check shapes of input arrays easily
5
- Author-email: 34j <34j.95a2p@simplelogin.com>
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
@@ -1,4 +1,4 @@
1
- from array_api_shape_check._main import _get_operand_names
1
+ from array_api_shape_check._main import _get_operand_names # noqa: PLC2701
2
2
 
3
3
 
4
4
  def test_get_operand_names():
@@ -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