You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stabilize runtime correctness, typing parity, and docs for release
- Async-safe @shapix.check: preserve coroutine behavior and memo lifetime
- Reject mixed Scalar in shape specs (e.g. F32[N, Scalar] raises TypeError)
- Fix DT64/TD64 to accept unit-qualified dtypes (datetime64[ns], etc.)
- Exclude booleans from numeric ScalarLike aliases and make_scalar_like_type
- Robust __version__ fallback when package metadata is unavailable
- Full type-checker parity: pyright, mypy, and ty via TypeVar/TypeAliasType
under TYPE_CHECKING; unified test suite across all three checkers
- Backend coverage: JAX/Torch Value(...) and boolean rejection tests
- Docs: async support, Scalar constraints, DT64/TD64, boolean semantics,
make_scalar_like_type location, checker-agnostic language
Copy file name to clipboardExpand all lines: README.md
+47-37Lines changed: 47 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ Shapix turns array shape annotations into **Python objects** that beartype valid
18
18
19
19
-**Zero boilerplate** — works with standard `@beartype` decorators and `beartype.claw` import hooks. No custom decorator required.
20
20
-**Cross-argument consistency** — named dimensions are enforced across all parameters and the return value within a single function call.
21
-
-**Static type checker friendly** — under `TYPE_CHECKING`, array types resolve to proper `NDArray` / `Array` / `Tensor` aliases. Pyright sees real types.
21
+
-**Static type checker friendly** — under `TYPE_CHECKING`, array types resolve to proper `NDArray` / `Array` / `Tensor` aliases. Works with pyright, mypy, and ty.
22
22
-**Readable annotations** — `F32[N, C, H, W]` reads like documentation.
ScalarLike types validate individual scalar values with range checking — no shape, just value:
435
+
ScalarLike types validate individual scalar values with range checking — no shape, just value.
436
+
437
+
> **Note:** Numeric scalar aliases (`I8ScalarLike`, `F32ScalarLike`, `NumScalarLike`, etc.) reject `bool` and `np.bool_` values. Python `bool` is a subclass of `int`, but shapix treats booleans as non-numeric. Use `BoolScalarLike` for boolean scalars.
432
438
433
439
```python
434
440
from shapix.numpy import I8ScalarLike, F32ScalarLike, U8ScalarLike
If you want a guarantee that cross-argument checking works regardless of how your code is called (by test runners, async frameworks, deep middleware stacks), `@shapix.check` removes all dependence on call-stack structure.
703
709
710
+
`@shapix.check` supports both sync and async functions. For async functions, the memo scope covers the full awaited execution, and `inspect.iscoroutinefunction()` is preserved on the decorated function.
711
+
704
712
**When you don't need it:** If you're using plain `@beartype` and your tests pass, the frame-based detection is working. Most applications never need `@shapix.check`.
705
713
706
714
### Manual checks with `check_context`
@@ -733,61 +741,58 @@ Shapix uses three key mechanisms:
733
741
734
742
3.**Thread-local storage** — Each thread gets its own memo stack via `threading.local()`, ensuring thread safety.
735
743
736
-
## Static type checkers (pyright / Pylance)
744
+
## Static type checkers (pyright, mypy, ty)
737
745
738
-
Shapix's pre-defined dimension symbols (`N`, `C`, `H`, `W`, ...) work out of the box with pyright and Pylance — under `TYPE_CHECKING` they resolve to `int` type aliases, so annotations like `F32[N, C]` are fully valid type expressions.
746
+
Shapix supports **pyright**, **mypy**, and **ty**. Under `TYPE_CHECKING`, pre-defined dimension symbols (`N`, `C`, `H`, `W`, …) resolve to `TypeVar`and array types resolve to `TypeAliasType`, so core annotations like `F32[N, C]` are valid type expressions across all three checkers.
739
747
740
-
However, some patterns produce type checker errors because they place **runtime values** where pyright expects **types**:
748
+
However, some patterns are fundamentally runtime-only and produce type checker errors regardless of the checker:
### Option A — Suppress `reportInvalidTypeForm` and wrap integers (recommended)
750
-
751
-
Add one line to your pyright config to silence operators, custom dimensions, and arithmetic globally. Then wrap bare integer literals in `Dimension()` to shift them to the same suppressed rule:
Most NumPy array types, plus `BF16` and `BF16Like`. NumPy-only extended-precision array aliases such as `F128` / `C256` stay in `shapix.numpy`. Both export `Like` types, `ScalarLike` types (re-exported from numpy), and `make_scalar_like_type`. JAX also exports `Tree`.
837
842
838
-
### Factories (`shapix`)
843
+
### Factories
844
+
845
+
From `shapix` (root):
839
846
840
847
`make_array_type(array_class, dtype_spec)` — custom array type
841
848
`make_array_like_type(dtype_spec, *, casting="same_kind", name="ArrayLike")` — custom Like type
842
-
`make_scalar_like_type(target_dtype, *, casting="same_kind", name="ScalarLike")` — custom ScalarLike type
0 commit comments