From 9bce4422cdf8665313b6c1b68879741d7e15192f Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Sat, 10 Jan 2026 22:37:04 +0100 Subject: [PATCH 1/4] torch.broadcast_arrays: make it return a tuple --- array_api_compat/torch/_aliases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/array_api_compat/torch/_aliases.py b/array_api_compat/torch/_aliases.py index e40183d8..0ebc5c0c 100644 --- a/array_api_compat/torch/_aliases.py +++ b/array_api_compat/torch/_aliases.py @@ -706,9 +706,9 @@ def astype( return x.to(dtype=dtype, copy=copy) -def broadcast_arrays(*arrays: Array) -> list[Array]: +def broadcast_arrays(*arrays: Array) -> tuple[Array, ...]: shape = torch.broadcast_shapes(*[a.shape for a in arrays]) - return [torch.broadcast_to(a, shape) for a in arrays] + return tuple(torch.broadcast_to(a, shape) for a in arrays) # Note that these named tuples aren't actually part of the standard namespace, # but I don't see any issue with exporting the names here regardless. From c746621fc973b64a5910d136bb7aa992cdbdcce4 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Sat, 10 Jan 2026 22:37:18 +0100 Subject: [PATCH 2/4] cupy.broadcast_arrays: make it return a tuple --- array_api_compat/cupy/_aliases.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/array_api_compat/cupy/_aliases.py b/array_api_compat/cupy/_aliases.py index 2e512fc8..badfe390 100644 --- a/array_api_compat/cupy/_aliases.py +++ b/array_api_compat/cupy/_aliases.py @@ -139,6 +139,11 @@ def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array: return cp.take_along_axis(x, indices, axis=axis) +# https://github.com/cupy/cupy/pull/9582 +def broadcast_arrays(*arrays: Array) -> tuple[Array, ...]: + return tuple(cp.broadcast_arrays(*arrays)) + + # These functions are completely new here. If the library already has them # (i.e., numpy 2.0), use the library version instead of our wrapper. if hasattr(cp, 'vecdot'): @@ -161,7 +166,8 @@ def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array: 'atan2', 'atanh', 'bitwise_left_shift', 'bitwise_invert', 'bitwise_right_shift', 'bool', 'concat', 'count_nonzero', 'pow', 'sign', - 'ceil', 'floor', 'trunc', 'take_along_axis'] + 'ceil', 'floor', 'trunc', 'take_along_axis', + 'broadcast_arrays',] def __dir__() -> list[str]: From 39331217c9f52bdcb651c7ecd87efdba89b14e8f Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Sun, 11 Jan 2026 11:07:42 +0100 Subject: [PATCH 3/4] torch.meshgrid: make it return tuple, not list --- array_api_compat/torch/_aliases.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/array_api_compat/torch/_aliases.py b/array_api_compat/torch/_aliases.py index 0ebc5c0c..2b1af799 100644 --- a/array_api_compat/torch/_aliases.py +++ b/array_api_compat/torch/_aliases.py @@ -881,10 +881,11 @@ def sign(x: Array, /) -> Array: return out -def meshgrid(*arrays: Array, indexing: Literal['xy', 'ij'] = 'xy') -> list[Array]: - # enforce the default of 'xy' - # TODO: is the return type a list or a tuple - return list(torch.meshgrid(*arrays, indexing=indexing)) +def meshgrid(*arrays: Array, indexing: Literal['xy', 'ij'] = 'xy') -> tuple[Array, ...]: + # torch <= 2.9 emits a UserWarning: "torch.meshgrid: in an upcoming release, it + # will be required to pass the indexing argument." + # Thus always pass it explicitly. + return torch.meshgrid(*arrays, indexing=indexing) __all__ = ['asarray', 'result_type', 'can_cast', From d193b8679331ae44246d10e89d8c9e69be03da86 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Sun, 11 Jan 2026 11:19:38 +0100 Subject: [PATCH 4/4] __array_namespace_info().devices() : returns a tuple not list --- array_api_compat/cupy/_info.py | 2 +- array_api_compat/dask/array/_info.py | 4 ++-- array_api_compat/numpy/_info.py | 4 ++-- array_api_compat/torch/_info.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/array_api_compat/cupy/_info.py b/array_api_compat/cupy/_info.py index 78e48a33..aef10e85 100644 --- a/array_api_compat/cupy/_info.py +++ b/array_api_compat/cupy/_info.py @@ -333,4 +333,4 @@ def devices(self): __array_namespace_info__.dtypes """ - return [cuda.Device(i) for i in range(cuda.runtime.getDeviceCount())] + return tuple(cuda.Device(i) for i in range(cuda.runtime.getDeviceCount())) diff --git a/array_api_compat/dask/array/_info.py b/array_api_compat/dask/array/_info.py index 2f39fc4b..3a7285d5 100644 --- a/array_api_compat/dask/array/_info.py +++ b/array_api_compat/dask/array/_info.py @@ -379,7 +379,7 @@ def dtypes( return res raise ValueError(f"unsupported kind: {kind!r}") - def devices(self) -> list[Device]: + def devices(self) -> tuple[Device]: """ The devices supported by Dask. @@ -404,4 +404,4 @@ def devices(self) -> list[Device]: ['cpu', DASK_DEVICE] """ - return ["cpu", _DASK_DEVICE] + return ("cpu", _DASK_DEVICE) diff --git a/array_api_compat/numpy/_info.py b/array_api_compat/numpy/_info.py index c625c13e..9ba004da 100644 --- a/array_api_compat/numpy/_info.py +++ b/array_api_compat/numpy/_info.py @@ -332,7 +332,7 @@ def dtypes( return res raise ValueError(f"unsupported kind: {kind!r}") - def devices(self) -> list[Device]: + def devices(self) -> tuple[Device]: """ The devices supported by NumPy. @@ -357,7 +357,7 @@ def devices(self) -> list[Device]: ['cpu'] """ - return ["cpu"] + return ("cpu",) __all__ = ["__array_namespace_info__"] diff --git a/array_api_compat/torch/_info.py b/array_api_compat/torch/_info.py index 818e5d37..050c7846 100644 --- a/array_api_compat/torch/_info.py +++ b/array_api_compat/torch/_info.py @@ -366,4 +366,4 @@ def devices(self): break i += 1 - return devices + return tuple(devices)