Skip to main content

ndlike

NumPy arrays, JAX arrays, and PyTorch tensors provide similar primitives for indexing, reshaping, stacking, and numerical operations. ndlike provides tools to build wrappers around these types that behave like the underlying arrays, but whose elements represent custom composite values—such as vectors or distributions—instead of individual numbers.

Protocols and reusable base classes handle array interfaces and backend function dispatch. Protected axes distinguish collection dimensions from each element's internal dimensions, so indexing, reshaping, or stacking a collection preserves the structure of its elements.

Installation

Requires Python 3.12 or newer.

pip install ndlike
pip install 'ndlike[torch]'
pip install 'ndlike[jax]'

NumPy and flextype are core dependencies. Torch and JAX are optional and are never imported by the backend-independent modules. Import backend modules explicitly.

Array protocols and base classes

ndlike.array_like.ArrayLike describes indexing, shape, and metadata rather than just convertibility to an array (as in numpy.typing.ArrayLike). It does not require the full numerical Array API. ArrayLikeWithoutSize covers the shared interface without NumPy/JAX's integer size property, since Torch uses a method.

Backend-specific APIs build on these protocols:

Module Protocol Conversion helper Conversion hook
ndlike.array_like NumpyLike to_numpy_like __array_like__
ndlike.torch_like TorchLike to_torch_like __torch_like__
ndlike.jax_like JaxLike to_jax_like __jax_like__

Each module also provides matching Implementation and Convertible classes, such as NumpyLikeImplementation and NumpyLikeConvertible.

Use the array protocols to type inputs, or subclass an implementation base to reuse convenience methods while supplying your representation's metadata and operation-dispatch hooks. NumPy uses __array_function__ / __array_ufunc__, Torch uses __torch_function__, and ndlike supplies __jax_function__ for JAX.

Conversion helpers call the conversion hook when an input satisfies the matching convertible protocol: the core array interface plus the hook, not the hook alone. This lets custom types preserve their structure instead of becoming raw arrays. Otherwise, the helpers fall back to numpy.asanyarray, torch.as_tensor, and jax.numpy.asarray, respectively. NumPy retains __array_like__ for backward compatibility and consistency with NumPy's __array__.

Protected axes

Protected-axis base classes give structured objects array-like behavior over their batch dimensions while preserving trailing internal dimensions. For example, a batch of six 3D vectors should have logical shape (6,), not (6, 3):

from dataclasses import dataclass
from typing import ClassVar

import numpy as np

from ndlike.protected_axis.numpy import NumpyAxisProtected


@dataclass
class Vectors(NumpyAxisProtected[np.ndarray]):
    array: np.ndarray
    protected_axes: ClassVar[dict[str, int]] = {"array": 1}


vectors = Vectors(np.ones((6, 3)))
assert vectors.shape == (6,)
assert vectors.protected_shape == (3,)
assert vectors[0].array.shape == (3,)

grid = vectors.reshape(2, 3)
assert grid.shape == (2, 3)
assert grid.array.shape == (2, 3, 3)

stacked = np.stack([vectors, vectors])
assert isinstance(stacked, Vectors)
assert stacked.shape == (2, 6)

protected_axes maps field names to the number of trailing axes to preserve. Multiple fields can have different internal shapes while sharing the same batch shape; indexing and supported shape operations update them together. Dataclasses work out of the box; other classes can override with_protected_values to reconstruct results.

Numerical operations are opt-in: use permitted_functions (for example, {np.mean}) and, for NumPy ufuncs, permitted_ufuncs (for example, {np.add: ["__call__", "reduce"]}). Supported reductions operate on batch axes, leaving internal axes intact.

The corresponding backend classes are TorchAxisProtected in ndlike.protected_axis.torch and JaxAxisProtected in ndlike.protected_axis.jax.

JAX function dispatch

JAX has no native equivalent of NumPy's __array_function__. For custom objects, use wrappers from ndlike.jax_functions, such as jax_reshape, jax_stack, and jax_mean, instead of the corresponding jax.numpy functions. They dispatch to __jax_function__ on custom types and call JAX normally for native arrays. jax_function_dispatch lets you add the same dispatch behavior to your own functions. JaxLikeImplementation also provides dataclass-based pytree support for JAX transformations such as jax.jit and jax.vmap.

Development

uv sync --all-extras
uv run pytest
uv run prek install
uv run prek run --all-files
uv build

Dependency groups follow flextype: lint contains Ruff and ty, test contains pytest, and dev includes both groups plus prek. Development Torch wheels use the CPU index on Linux and Windows. Type checking requires both backend extras.

scripts/check_backend_naming.py enforces backend prefixes on definitions (BKN001) and restricts runtime Torch/JAX imports to their respective backend-prefixed modules (BKN002). Type-only imports are exempt. Intentional exceptions use an explicit # noqa: BKN001 or # noqa: BKN002 on the opening line.

Metadata

Release files for ndlike 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ndlike 0.1.1
File Size Uploaded Provenance
ndlike-0.1.1.tar.gz 49.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ndlike 0.1.1
File Interpreter ABI Platform
ndlike-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 105.0 kB

Release files / ndlike-0.1.1.tar.gz

Download URL ndlike-0.1.1.tar.gz
Size 49.5 kB
Tags Source
SHA-256 checksum
How to use checksums
c2bc1afac4e5b60a4cdaa76fa2e6e443c73d73f95e45da60e01c70f99fdb3eb9
BLAKE2b-256 checksum
How to use checksums
6a309570eb3bb7eb93b0c30286eee673a26c745136827cedef69c78c5821b838
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / ndlike-0.1.1-py3-none-any.whl

Download URL ndlike-0.1.1-py3-none-any.whl
Size 55.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e37273e2857418a5d93f9577c9fd788c03d10c5f329b10a6ca9a3c8be599e1bd
BLAKE2b-256 checksum
How to use checksums
614bb244c5de15f4733dc681f69d2ea56ee2fe3ec7e45816943c11bfb9868061
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for ndlike 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ndlike-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page