src/appose/shm.py
- NDArray.__init__: Added optional dims: list[str] | None = None parameter with validation that its length matches shape
- NDArray.__str__: Shows dims when present
- NDArray.xarray(): New method — returns an xarray.DataArray wrapping the same shared memory, with dims preserved. Requires numpy + xarray.
- Encoder (_encode_ndarray): Emits dims only when non-None (keeps wire format compact for the common no-dims case)
- Decoder: Uses m.get("dims") so missing dims field decodes as None (backward compat with older senders)
tests/util/test_message.py
- test_encode_with_dims / test_decode_with_dims: Round-trip encoding/decoding with dims
- test_decode_ignores_unknown_fields: Explicit backward-compat test — verifies unknown fields don't cause errors
tests/test_shm.py
- test_ndarray_dims: Integration test — dims survive the wire protocol across processes
- test_ndarray_dims_none: Backward compat — no dims → None
- test_ndarray_dims_length_mismatch: Validation error
- test_ndarray_xarray / test_ndarray_xarray_no_dims: xarray conversion (skipped when numpy/xarray unavailable)