16
16
from collections .abc import Generator , Iterator , Mapping
17
17
from contextlib import ExitStack
18
18
from io import BytesIO
19
- from os import listdir
20
19
from pathlib import Path
21
20
from typing import TYPE_CHECKING , Any , Final , Literal , cast
22
21
from unittest .mock import patch
@@ -3638,34 +3637,54 @@ def roundtrip_dir(
3638
3637
3639
3638
@pytest .mark .parametrize ("consolidated" , [True , False , None ])
3640
3639
@pytest .mark .parametrize ("write_empty" , [True , False , None ])
3641
- @pytest .mark .skipif (
3642
- has_zarr_v3 , reason = "zarr-python 3.x removed write_empty_chunks"
3643
- )
3644
3640
def test_write_empty (
3645
- self , consolidated : bool | None , write_empty : bool | None
3641
+ self ,
3642
+ consolidated : bool | None ,
3643
+ write_empty : bool | None ,
3646
3644
) -> None :
3647
- if write_empty is False :
3648
- expected = ["0.1.0" , "1.1.0" ]
3645
+ def assert_expected_files (expected : list [str ], store : str ) -> None :
3646
+ """Convenience for comparing with actual files written"""
3647
+ ls = []
3648
+ test_root = os .path .join (store , "test" )
3649
+ for root , _ , files in os .walk (test_root ):
3650
+ ls .extend (
3651
+ [
3652
+ os .path .join (root , f ).removeprefix (test_root ).lstrip ("/" )
3653
+ for f in files
3654
+ ]
3655
+ )
3656
+
3657
+ assert set (expected ) == set (
3658
+ [
3659
+ file .lstrip ("c/" )
3660
+ for file in ls
3661
+ if (file not in (".zattrs" , ".zarray" , "zarr.json" ))
3662
+ ]
3663
+ )
3664
+
3665
+ # The zarr format is set by the `default_zarr_format`
3666
+ # pytest fixture that acts on a superclass
3667
+ zarr_format_3 = has_zarr_v3 and zarr .config .config ["default_zarr_format" ] == 3
3668
+ if (write_empty is False ) or (write_empty is None and has_zarr_v3 ):
3669
+ expected = ["0.1.0" ]
3649
3670
else :
3650
3671
expected = [
3651
3672
"0.0.0" ,
3652
3673
"0.0.1" ,
3653
3674
"0.1.0" ,
3654
3675
"0.1.1" ,
3655
- "1.0.0" ,
3656
- "1.0.1" ,
3657
- "1.1.0" ,
3658
- "1.1.1" ,
3659
3676
]
3660
3677
3661
- ds = xr .Dataset (
3662
- data_vars = {
3663
- "test" : (
3664
- ("Z" , "Y" , "X" ),
3665
- np .array ([np .nan , np .nan , 1.0 , np .nan ]).reshape ((1 , 2 , 2 )),
3666
- )
3667
- }
3668
- )
3678
+ if zarr_format_3 :
3679
+ data = np .array ([0.0 , 0 , 1.0 , 0 ]).reshape ((1 , 2 , 2 ))
3680
+ # transform to the path style of zarr 3
3681
+ # e.g. 0/0/1
3682
+ expected = [e .replace ("." , "/" ) for e in expected ]
3683
+ else :
3684
+ # use nan for default fill_value behaviour
3685
+ data = np .array ([np .nan , np .nan , 1.0 , np .nan ]).reshape ((1 , 2 , 2 ))
3686
+
3687
+ ds = xr .Dataset (data_vars = {"test" : (("Z" , "Y" , "X" ), data )})
3669
3688
3670
3689
if has_dask :
3671
3690
ds ["test" ] = ds ["test" ].chunk (1 )
@@ -3681,17 +3700,42 @@ def test_write_empty(
3681
3700
write_empty_chunks = write_empty ,
3682
3701
)
3683
3702
3703
+ # check expected files after a write
3704
+ assert_expected_files (expected , store )
3705
+
3684
3706
with self .roundtrip_dir (
3685
3707
ds ,
3686
3708
store ,
3687
- {"mode" : "a" , "append_dim" : "Z" , "write_empty_chunks" : write_empty },
3709
+ save_kwargs = {
3710
+ "mode" : "a" ,
3711
+ "append_dim" : "Z" ,
3712
+ "write_empty_chunks" : write_empty ,
3713
+ },
3688
3714
) as a_ds :
3689
3715
expected_ds = xr .concat ([ds , ds ], dim = "Z" )
3690
3716
3691
- assert_identical (a_ds , expected_ds )
3692
-
3693
- ls = listdir (os .path .join (store , "test" ))
3694
- assert set (expected ) == set ([file for file in ls if file [0 ] != "." ])
3717
+ assert_identical (a_ds , expected_ds .compute ())
3718
+ # add the new files we expect to be created by the append
3719
+ # that was performed by the roundtrip_dir
3720
+ if (write_empty is False ) or (write_empty is None and has_zarr_v3 ):
3721
+ expected .append ("1.1.0" )
3722
+ else :
3723
+ if not has_zarr_v3 :
3724
+ # TODO: remove zarr3 if once zarr issue is fixed
3725
+ # https://github.com/zarr-developers/zarr-python/issues/2931
3726
+ expected .extend (
3727
+ [
3728
+ "1.1.0" ,
3729
+ "1.0.0" ,
3730
+ "1.0.1" ,
3731
+ "1.1.1" ,
3732
+ ]
3733
+ )
3734
+ else :
3735
+ expected .append ("1.1.0" )
3736
+ if zarr_format_3 :
3737
+ expected = [e .replace ("." , "/" ) for e in expected ]
3738
+ assert_expected_files (expected , store )
3695
3739
3696
3740
def test_avoid_excess_metadata_calls (self ) -> None :
3697
3741
"""Test that chunk requests do not trigger redundant metadata requests.
0 commit comments