@@ -56,6 +56,19 @@ def resolve_batched(codec: Codec, chunk_specs: Iterable[ArraySpec]) -> Iterable[
5656 return [codec .resolve_metadata (chunk_spec ) for chunk_spec in chunk_specs ]
5757
5858
59+ def fill_value_or_default (chunk_spec : ArraySpec ) -> Any :
60+ fill_value = chunk_spec .fill_value
61+ if fill_value is None :
62+ # Zarr V2 allowed `fill_value` to be null in the metadata.
63+ # Zarr V3 requires it to be set. This has already been
64+ # validated when decoding the metadata, but we support reading
65+ # Zarr V2 data and need to support the case where fill_value
66+ # is None.
67+ return _default_fill_value (dtype = chunk_spec .dtype )
68+ else :
69+ return fill_value
70+
71+
5972@dataclass (frozen = True )
6073class BatchedCodecPipeline (CodecPipeline ):
6174 """Default codec pipeline.
@@ -247,17 +260,7 @@ async def read_batch(
247260 if chunk_array is not None :
248261 out [out_selection ] = chunk_array
249262 else :
250- fill_value = chunk_spec .fill_value
251-
252- if fill_value is None :
253- # Zarr V2 allowed `fill_value` to be null in the metadata.
254- # Zarr V3 requires it to be set. This has already been
255- # validated when decoding the metadata, but we support reading
256- # Zarr V2 data and need to support the case where fill_value
257- # is None.
258- fill_value = _default_fill_value (dtype = chunk_spec .dtype )
259-
260- out [out_selection ] = fill_value
263+ out [out_selection ] = fill_value_or_default (chunk_spec )
261264 else :
262265 chunk_bytes_batch = await concurrent_map (
263266 [(byte_getter , array_spec .prototype ) for byte_getter , array_spec , * _ in batch_info ],
@@ -281,10 +284,7 @@ async def read_batch(
281284 tmp = tmp .squeeze (axis = drop_axes )
282285 out [out_selection ] = tmp
283286 else :
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
287+ out [out_selection ] = fill_value_or_default (chunk_spec )
288288
289289 def _merge_chunk_array (
290290 self ,
@@ -303,7 +303,7 @@ def _merge_chunk_array(
303303 shape = chunk_spec .shape ,
304304 dtype = chunk_spec .dtype ,
305305 order = chunk_spec .order ,
306- fill_value = chunk_spec . fill_value ,
306+ fill_value = fill_value_or_default ( chunk_spec ) ,
307307 )
308308 else :
309309 chunk_array = existing_chunk_array .copy () # make a writable copy
@@ -402,7 +402,7 @@ async def _read_key(
402402 chunk_array_batch .append (None ) # type: ignore[unreachable]
403403 else :
404404 if not chunk_spec .config .write_empty_chunks and chunk_array .all_equal (
405- chunk_spec . fill_value
405+ fill_value_or_default ( chunk_spec )
406406 ):
407407 chunk_array_batch .append (None )
408408 else :
0 commit comments