Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
([809](https://github.com/zarr-developers/VirtualiZarr/pull/809)).
By [Julia Signell](https://github.com/jsignell).

### Bug fixes

- Fix setting `fill_value` for Zarr V2 arrays if data type is a subtype of integer or float.
([#845](https://github.com/zarr-developers/VirtualiZarr/pull/845)).
By [Hauke Schulz](https://github.com/observingClouds).

## v2.2.1 (17th November 2025)

### Bug fixes
Expand Down
20 changes: 7 additions & 13 deletions virtualizarr/parsers/zarr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
from abc import ABC, abstractmethod
from collections.abc import Iterable
from pathlib import Path
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, cast

import zarr
from zarr.api.asynchronous import open_group as open_group_async
from zarr.core.dtype import parse_dtype
from zarr.core.group import GroupMetadata
from zarr.core.metadata import ArrayV3Metadata
from zarr.storage import ObjectStore
Expand Down Expand Up @@ -194,20 +195,13 @@ def get_metadata(self, zarr_array: ZarrArrayType) -> ArrayV3Metadata:

if v2_metadata.fill_value is None:
v2_dict = v2_metadata.to_dict()
v2_dict["fill_value"] = 0
v2_dtype = parse_dtype(cast(Any, v2_dict["dtype"]), zarr_format=2)
fill_value = v2_dtype.default_scalar()
v2_dict["fill_value"] = (
fill_value.item() if hasattr(fill_value, "item") else fill_value
)
temp_v2 = ArrayV2Metadata.from_dict(v2_dict)
v3_metadata = _convert_array_metadata(temp_v2)

# Replace with proper default for the data type
default_scalar = v3_metadata.data_type.default_scalar()
fill_value = (
default_scalar.item()
if hasattr(default_scalar, "item")
else default_scalar
)
v3_dict = v3_metadata.to_dict()
v3_dict["fill_value"] = fill_value
v3_metadata = ArrayV3Metadata.from_dict(v3_dict)
else:
# Normal conversion; allow other errors to propagate.
v3_metadata = _convert_array_metadata(v2_metadata)
Expand Down
14 changes: 12 additions & 2 deletions virtualizarr/tests/test_parsers/test_zarr.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,17 @@ async def get_meta():


@SKIP_OLDER_ZARR_PYTHON
def test_v2_metadata_with_none_fill_value():
@pytest.mark.parametrize(
"dtype",
[
"int32",
"uint8",
"float64",
"bool",
"U10",
],
)
def test_v2_metadata_with_none_fill_value(dtype):
"""Test V2 metadata conversion when fill_value is None."""
import asyncio

Expand All @@ -273,7 +283,7 @@ def test_v2_metadata_with_none_fill_value():
_ = zarr.create(
shape=(5, 10),
chunks=(5, 5),
dtype="int32",
dtype=dtype,
store=store,
zarr_format=2,
fill_value=None,
Expand Down
Loading