Skip to content

Commit 3bf3622

Browse files
committed
Use implicit fill values for zarr v2
1 parent 6454c69 commit 3bf3622

File tree

5 files changed

+33
-5
lines changed

5 files changed

+33
-5
lines changed

src/zarr/codecs/pipeline.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from zarr.core.common import ChunkCoords, concurrent_map
1818
from zarr.core.config import config
1919
from zarr.core.indexing import SelectorTuple, is_scalar, is_total_slice
20+
from zarr.core.metadata.v2 import default_fill_value
2021
from zarr.registry import register_pipeline
2122

2223
if TYPE_CHECKING:
@@ -247,7 +248,13 @@ async def read_batch(
247248
if chunk_array is not None:
248249
out[out_selection] = chunk_array
249250
else:
250-
out[out_selection] = chunk_spec.fill_value
251+
fill_value = chunk_spec.fill_value
252+
253+
# this should maybe be version specific?
254+
if fill_value is None:
255+
fill_value = default_fill_value(dtype=chunk_spec.dtype)
256+
257+
out[out_selection] = fill_value
251258
else:
252259
chunk_bytes_batch = await concurrent_map(
253260
[
@@ -274,7 +281,10 @@ async def read_batch(
274281
tmp = tmp.squeeze(axis=drop_axes)
275282
out[out_selection] = tmp
276283
else:
277-
out[out_selection] = chunk_spec.fill_value
284+
fill_value = chunk_spec.fill_value
285+
if fill_value is None:
286+
fill_value = default_fill_value(dtype=chunk_spec.dtype)
287+
out[out_selection] = fill_value
278288

279289
def _merge_chunk_array(
280290
self,

src/zarr/core/array.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ async def _create_v2(
376376
chunks=chunks,
377377
order=order,
378378
dimension_separator=dimension_separator,
379-
fill_value=0 if fill_value is None else fill_value,
379+
fill_value=fill_value,
380380
compressor=compressor,
381381
filters=filters,
382382
attributes=attributes,

src/zarr/core/metadata/v2.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ def __init__(
6262
order_parsed = parse_indexing_order(order)
6363
dimension_separator_parsed = parse_separator(dimension_separator)
6464
filters_parsed = parse_filters(filters)
65-
fill_value_parsed = parse_fill_value(fill_value, dtype=data_type_parsed)
65+
if fill_value is None:
66+
fill_value_parsed = None
67+
else:
68+
fill_value_parsed = parse_fill_value(fill_value, dtype=data_type_parsed)
6669
attributes_parsed = parse_attributes(attributes)
6770

6871
object.__setattr__(self, "shape", shape_parsed)
@@ -273,3 +276,7 @@ def parse_fill_value(fill_value: object, dtype: np.dtype[Any]) -> Any:
273276
raise ValueError(msg) from e
274277

275278
return fill_value
279+
280+
281+
def default_fill_value(dtype: np.dtype[Any]) -> Any:
282+
return dtype.type(0)

tests/v3/test_metadata/test_v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_parse_zarr_format_invalid(data: Any) -> None:
2828
@pytest.mark.parametrize("attributes", [None, {"foo": "bar"}])
2929
@pytest.mark.parametrize("filters", [None, (), (numcodecs.GZip(),)])
3030
@pytest.mark.parametrize("compressor", [None, numcodecs.GZip()])
31-
@pytest.mark.parametrize("fill_value", [0, 1])
31+
@pytest.mark.parametrize("fill_value", [None, 0, 1])
3232
@pytest.mark.parametrize("order", ["C", "F"])
3333
@pytest.mark.parametrize("dimension_separator", [".", "/", None])
3434
def test_metadata_to_dict(

tests/v3/test_v2.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ def test_simple(store: StorePath) -> None:
3131
assert np.array_equal(data, a[:, :])
3232

3333

34+
def test_implicit_fill_value(store: StorePath) -> None:
35+
arr = zarr.open_array(store=store, shape=(4,), fill_value=None, zarr_format=2)
36+
assert arr.metadata.fill_value is None
37+
assert arr.metadata.to_dict()["fill_value"] is None
38+
result = arr[:]
39+
expected = np.zeros(arr.shape, dtype=arr.dtype)
40+
np.testing.assert_array_equal(result, expected)
41+
42+
3443
def test_codec_pipeline() -> None:
3544
# https://github.com/zarr-developers/zarr-python/issues/2243
3645
store = MemoryStore(mode="w")
@@ -46,3 +55,5 @@ def test_codec_pipeline() -> None:
4655
result = array[:]
4756
expected = np.ones(1)
4857
np.testing.assert_array_equal(result, expected)
58+
59+

0 commit comments

Comments
 (0)