diff --git a/src/zarr/core/array.py b/src/zarr/core/array.py index e5fc707f0..6af8c3322 100644 --- a/src/zarr/core/array.py +++ b/src/zarr/core/array.py @@ -977,9 +977,10 @@ def _iter_chunk_regions( @property def nbytes(self) -> int: """ - The number of bytes that can be stored in this array. + The number of bytes that can be stored in the chunks of this array. """ - return self.nchunks * self.dtype.itemsize + # TODO: how can this be meaningful for variable-length types? + return int(np.prod(self.shape) * self.dtype.itemsize) async def _get_selection( self, diff --git a/tests/test_array.py b/tests/test_array.py index 3eb317e50..cf722c738 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -776,3 +776,21 @@ async def test_special_complex_fill_values_roundtrip(fill_value: Any, expected: assert content is not None actual = json.loads(content.to_bytes()) assert actual["fill_value"] == expected + + +@pytest.mark.parametrize("shape", [(1,), (2, 3), (4, 5, 6)]) +@pytest.mark.parametrize("dtype", ["uint8", "float32"]) +@pytest.mark.parametrize("array_type", ["async", "sync"]) +async def test_nbytes( + shape: tuple[int, ...], dtype: str, array_type: Literal["async", "sync"] +) -> None: + """ + Test that the ``nbytes`` attribute of an Array or AsyncArray correctly reports the capacity of + the chunks of that array. + """ + store = MemoryStore() + arr = Array.create(store=store, shape=shape, dtype=dtype, fill_value=0) + if array_type == "async": + assert arr._async_array.nbytes == np.prod(arr.shape) * arr.dtype.itemsize + else: + assert arr.nbytes == np.prod(arr.shape) * arr.dtype.itemsize