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
Add symbolic PyTree annotations, expand tox/CI with jax 0.7-0.9 and optree/beartype compat
Replace string-based PyTree structure specs ("T", "S T", "T ...") with
symbolic Structure class and pre-exported T/S symbols. Add composite
(S[T]), prefix (T[...]), and suffix (..., T) operators. Include optree
as optional dependency with full version compat matrix (0.14-0.19),
beartype compat (0.20-0.22), and jax 0.5-0.9.
### Package-wide instrumentation with `beartype.claw`
@@ -340,28 +406,29 @@ shapix_this_package()
340
406
341
407
Every function in your package that uses shapix type annotations will be checked automatically.
342
408
343
-
### Explicit memo management with `@shapix.check`
409
+
### How cross-argument checking works (the memo)
344
410
345
-
The frame-based memo works automatically with `@beartype` in virtually all cases. For exotic call-stack scenarios, or to combine memo management with custom `BeartypeConf`, use the explicit decorator:
411
+
A **dimension memo** maps dimension names to sizes (e.g., `N→4`, `C→3`). Each function call gets a fresh memo. All parameter checks within that call share the same memo — that's how shapix knows `N=4` in `x` must match `N=4` in `y`.
346
412
347
-
```python
348
-
import shapix
349
-
from beartype import beartype
413
+
This happens **automatically** with `@beartype`. Shapix detects the beartype wrapper frame via `sys._getframe()` and associates a memo with it. No extra decorator needed.
350
414
351
-
# Option 1: Memo only — pair with @beartype
352
-
@shapix.check
353
-
@beartype
354
-
deff(x: F32[N, C]) -> F32[N, C]:
355
-
...
415
+
### `@shapix.check` (optional)
356
416
357
-
# Option 2: Memo + beartype combined with custom config
358
-
from beartype._conf.confmain import BeartypeConf
417
+
`@shapix.check` provides **explicit** memo management. It's useful in two scenarios:
418
+
419
+
1.**Combining memo with custom `BeartypeConf`** — a single decorator instead of stacking two:
420
+
421
+
```python
422
+
from beartype import BeartypeConf
359
423
360
424
@shapix.check(conf=BeartypeConf())
361
-
deff(x: F32[N, C]) -> F32[N, C]:
362
-
...
425
+
deff(x: F32[N, C]) -> F32[N, C]: ...
363
426
```
364
427
428
+
2.**Exotic call stacks** where frame-based detection is unreliable (deep decorator chains, recursive wrappers).
429
+
430
+
For normal usage, just use `@beartype` — it works out of the box.
431
+
365
432
### Manual checks with `check_context`
366
433
367
434
For `isinstance`-style checks outside of decorated functions, use `check_context` with beartype's `is_bearable`:
@@ -383,7 +450,7 @@ Shapix uses three key mechanisms:
383
450
384
451
1.**`Annotated[T, Is[validator]]`** — Each array type annotation (e.g., `F32[N, C]`) produces a `typing.Annotated` type with a beartype `Is[...]` validator. This lets beartype handle all the dispatch natively.
385
452
386
-
2.**Frame-based memo management** — beartype's `Is[validator]` call stack is deterministic: `validator → _is_valid_bool → beartype_wrapper`. All parameter checks for one function call share the same wrapper frame. Shapix identifies this frame via `sys._getframe()` and associates a dimension memo (name → size bindings) with it. This is how cross-argument consistency works with zero boilerplate.
453
+
2.**Frame-based memo** — beartype's `Is[validator]` call stack is deterministic: `validator → _is_valid_bool → beartype_wrapper`. All parameter checks for one function call share the same wrapper frame. Shapix identifies this frame via `sys._getframe()` and associates a dimension memo (name → size bindings) with it. This is how cross-argument consistency works with zero boilerplate.
387
454
388
455
3.**Thread-local storage** — Each thread gets its own memo stack via `threading.local()`, ensuring thread safety.
0 commit comments