array-api-shape-check 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl

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,4 +1,4 @@
1
- __version__ = "0.1.2"
1
+ __version__ = "0.1.3"
2
2
  from ._main import (
3
3
  InconsistentNdimError,
4
4
  InconsistentNdimErrorMultipleSolutions,
@@ -77,26 +77,38 @@ class SubscriptInfoFromShape:
77
77
 
78
78
 
79
79
  class InconsistentNdimError(ValueError):
80
- pass
80
+ shapes: Sequence[int] | None
81
+ ndims: Sequence[int]
82
+ reason: str
81
83
 
82
84
 
83
85
  class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
84
- def __init__(self, reason: str, *args: object) -> None:
86
+ def __init__(
87
+ self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
88
+ ) -> None:
89
+ self.ndims = ndims
90
+ self.reason = reason
91
+ self.shapes = shapes
85
92
  super().__init__(
86
93
  f"Inconsistent ndims: there are multiple possible solutions "
87
94
  "to determine the number of dimensions "
88
- f"for variable subscripts [{reason}]",
89
- *args,
95
+ f"for variable subscripts [{reason}]"
96
+ f"\nndims: {ndims}" + (f"\nshapes: {shapes}" if shapes is not None else "")
90
97
  )
91
98
 
92
99
 
93
100
  class InconsistentNdimErrorNoSolutions(InconsistentNdimError):
94
- def __init__(self, reason: str, *args: object) -> None:
101
+ def __init__(
102
+ self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
103
+ ) -> None:
104
+ self.ndims = ndims
105
+ self.reason = reason
106
+ self.shapes = shapes
95
107
  super().__init__(
96
108
  f"Inconsistent ndims: there are no solution "
97
109
  f"to determine the number of dimensions "
98
- f"for variable subscripts [{reason}]",
99
- *args,
110
+ f"for variable subscripts [{reason}]"
111
+ f"\nndims: {ndims}" + (f"\nshapes: {shapes}" if shapes is not None else "")
100
112
  )
101
113
 
102
114
 
@@ -258,9 +270,8 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
258
270
  subscript for subscript in info.unique.values() if subscript.is_variable
259
271
  ]
260
272
  if len(info_variable_unique) > len(info.all):
261
- raise InconsistentNdimErrorMultipleSolutions("number of variables")
273
+ raise InconsistentNdimErrorMultipleSolutions(ndims, "number of variables")
262
274
  rhs = np.asarray(ndims, dtype=int)
263
- del ndims
264
275
  mat = np.zeros((len(info.all), len(info_variable_unique)), dtype=int)
265
276
  for i, info_array in enumerate(info.all):
266
277
  for subscript in info_array:
@@ -273,19 +284,19 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
273
284
  # solve overdetermined linear equations using least squares method
274
285
  variable_dims, residuals, rank, _singular_values = np.linalg.lstsq(mat, rhs, rcond=None)
275
286
  if rank != len(info_variable_unique):
276
- raise InconsistentNdimErrorMultipleSolutions("rank")
287
+ raise InconsistentNdimErrorMultipleSolutions(ndims, "rank")
277
288
  if residuals.size > 0 and not np.isclose(residuals[0], 0):
278
- raise InconsistentNdimErrorNoSolutions("residuals")
289
+ raise InconsistentNdimErrorNoSolutions(ndims, "residuals")
279
290
  variable_dims = np.round(variable_dims).astype(int)
280
291
  if np.any(variable_dims < 0):
281
- raise InconsistentNdimErrorNoSolutions("negative")
292
+ raise InconsistentNdimErrorNoSolutions(ndims, "negative")
282
293
  return {
283
294
  subscript.name: int(variable_dims[j]) for j, subscript in enumerate(info_variable_unique)
284
295
  }
285
296
 
286
297
 
287
298
  def _parse_shapes(
288
- subscripts: str, /, *operands: Array | tuple[int, ...]
299
+ subscripts: str, /, *operands: Array | tuple[int | None, ...]
289
300
  ) -> tuple[tuple[SubscriptInfoFromShapeItemUnchecked, ...], ...]:
290
301
  info = parse_subscripts(subscripts)
291
302
  if len(info.all) != len(operands):
@@ -309,7 +320,10 @@ def _parse_shapes(
309
320
  shapes += (shape,) # type: ignore
310
321
  del operands
311
322
  ndims = [len(shape) for shape in shapes]
312
- name_to_ndim = defaultdict(lambda: 1, parse_variable_ndim(subscripts, ndims))
323
+ try:
324
+ name_to_ndim = defaultdict(lambda: 1, parse_variable_ndim(subscripts, ndims))
325
+ except InconsistentNdimError as e:
326
+ raise type(e)(e.ndims, e.reason, shapes) from e
313
327
  del subscripts, ndims
314
328
  info_all: tuple[tuple[SubscriptInfoFromShapeItemUnchecked, ...], ...] = ()
315
329
  for info_array, shape in zip(info.all, shapes, strict=False):
@@ -328,7 +342,7 @@ def _parse_shapes(
328
342
 
329
343
 
330
344
  def check_shapes(
331
- subscripts: str, /, *operands: Array | tuple[int, ...], names: str | None = None
345
+ subscripts: str, /, *operands: Array | tuple[int | None, ...], names: str | None = None
332
346
  ) -> SubscriptInfoFromShape:
333
347
  """
334
348
  Parse variable subscript ndims by solving linear equations.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: array-api-shape-check
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Check shapes of input arrays easily
5
5
  Author-email: 34j <34j.95a2p@simplelogin.com>
6
6
  License-Expression: MIT
@@ -0,0 +1,8 @@
1
+ array_api_shape_check/__init__.py,sha256=8i9ZV_x6HXtVd0g7N3ec190lQ1LUC2s93A9p-J3C9WI,940
2
+ array_api_shape_check/_main.py,sha256=LqwDK6OD9ldcUaXmmbG5aBXzOW0gEJuu1iAe9rs2BiY,16652
3
+ array_api_shape_check/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ array_api_shape_check-0.1.3.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
5
+ array_api_shape_check-0.1.3.dist-info/METADATA,sha256=of_gXs9JcFp-b0KQwa9Sbf8GIXPvChmU5VGfvBWyYOQ,6213
6
+ array_api_shape_check-0.1.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
+ array_api_shape_check-0.1.3.dist-info/top_level.txt,sha256=pirw2DeaWnDU_rSg3CZ1MsE-tJWEvndYSQG0illDMkI,22
8
+ array_api_shape_check-0.1.3.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- array_api_shape_check/__init__.py,sha256=peDt2aytKiIHNe9K5YRB8VJG15wxDIt0bKm7Z6Wu8s8,940
2
- array_api_shape_check/_main.py,sha256=kqGml_xsXX1CtieBZDyyd_m-_kBqe-F-oj4PVpfKsek,16029
3
- array_api_shape_check/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- array_api_shape_check-0.1.2.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
5
- array_api_shape_check-0.1.2.dist-info/METADATA,sha256=bQKTAYo0XcoLyASUyChwsJ0RdNwlb-CBN5oHQrGkgV4,6213
6
- array_api_shape_check-0.1.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
- array_api_shape_check-0.1.2.dist-info/top_level.txt,sha256=pirw2DeaWnDU_rSg3CZ1MsE-tJWEvndYSQG0illDMkI,22
8
- array_api_shape_check-0.1.2.dist-info/RECORD,,