From c075acf17b08fe465c088a9a4c39b4879c529218 Mon Sep 17 00:00:00 2001 From: stanbot8 Date: Mon, 27 Jul 2026 18:42:34 -0700 Subject: [PATCH 1/2] fix: accept an empty view without a copy --- array_api_strict/_manipulation_functions.py | 4 ++-- .../tests/test_manipulation_functions.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/array_api_strict/_manipulation_functions.py b/array_api_strict/_manipulation_functions.py index c2dcccf4..c2397fde 100644 --- a/array_api_strict/_manipulation_functions.py +++ b/array_api_strict/_manipulation_functions.py @@ -122,8 +122,8 @@ def reshape(x: Array, /, shape: tuple[int, ...], *, copy: bool | None = None) -> reshaped = np.reshape(data, shape) - if copy is False and not np.shares_memory(data, reshaped): - raise AttributeError("Incompatible shape for in-place modification.") + if copy is False and data.size > 0 and not np.shares_memory(data, reshaped): + raise ValueError("Incompatible shape for a no-copy reshape.") return Array._new(reshaped, device=x.device) diff --git a/array_api_strict/tests/test_manipulation_functions.py b/array_api_strict/tests/test_manipulation_functions.py index bd247ee4..53b8fcf5 100644 --- a/array_api_strict/tests/test_manipulation_functions.py +++ b/array_api_strict/tests/test_manipulation_functions.py @@ -32,5 +32,15 @@ def test_reshape_copy(): a = asarray(np.ones((2, 3)).T) b = reshape(a, (3, 2), copy=True) - assert_raises(AttributeError, lambda: reshape(a, (2, 3), copy=False)) + assert_raises(ValueError, lambda: reshape(a, (2, 3), copy=False)) + + +def test_reshape_copy_false_keeps_an_empty_view(): + a = asarray(np.empty((0,))) + b = reshape(a, (0, 2), copy=False) + assert b.shape == (0, 2) + + a = asarray(np.empty((0, 2))) + b = reshape(a, (2, 0), copy=False) + assert b.shape == (2, 0) From c51195cc5e9ebe70ee3eacdf82a33022415aa4d6 Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Tue, 28 Jul 2026 16:18:29 +0200 Subject: [PATCH 2/2] Update array_api_strict/_manipulation_functions.py --- array_api_strict/_manipulation_functions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/array_api_strict/_manipulation_functions.py b/array_api_strict/_manipulation_functions.py index c2397fde..02dcf163 100644 --- a/array_api_strict/_manipulation_functions.py +++ b/array_api_strict/_manipulation_functions.py @@ -122,6 +122,7 @@ def reshape(x: Array, /, shape: tuple[int, ...], *, copy: bool | None = None) -> reshaped = np.reshape(data, shape) + # NB: `.size>0` works around that `x=np.asarray([]); np.shares_memory(x, x)` is False if copy is False and data.size > 0 and not np.shares_memory(data, reshaped): raise ValueError("Incompatible shape for a no-copy reshape.")