|
19 | 19 | from os import listdir
|
20 | 20 | from pathlib import Path
|
21 | 21 | from typing import TYPE_CHECKING, Any, Final, cast
|
| 22 | +from unittest.mock import patch |
22 | 23 |
|
23 | 24 | import numpy as np
|
24 | 25 | import pandas as pd
|
@@ -2862,6 +2863,47 @@ def create_zarr_target(self):
|
2862 | 2863 | yield tmp
|
2863 | 2864 |
|
2864 | 2865 |
|
| 2866 | +@requires_zarr |
| 2867 | +class TestZarrArrayWrapperCalls(TestZarrKVStoreV3): |
| 2868 | + def test_avoid_excess_metadata_calls(self) -> None: |
| 2869 | + """Test that chunk requests do not trigger redundant metadata requests. |
| 2870 | +
|
| 2871 | + This test targets logic in backends.zarr.ZarrArrayWrapper, asserting that calls |
| 2872 | + to retrieve chunk data after initialization do not trigger additional |
| 2873 | + metadata requests. |
| 2874 | +
|
| 2875 | + https://github.com/pydata/xarray/issues/8290 |
| 2876 | + """ |
| 2877 | + |
| 2878 | + import zarr |
| 2879 | + |
| 2880 | + ds = xr.Dataset(data_vars={"test": (("Z",), np.array([123]).reshape(1))}) |
| 2881 | + |
| 2882 | + # The call to retrieve metadata performs a group lookup. We patch Group.__getitem__ |
| 2883 | + # so that we can inspect calls to this method - specifically count of calls. |
| 2884 | + # Use of side_effect means that calls are passed through to the original method |
| 2885 | + # rather than a mocked method. |
| 2886 | + Group = zarr.hierarchy.Group |
| 2887 | + with ( |
| 2888 | + self.create_zarr_target() as store, |
| 2889 | + patch.object( |
| 2890 | + Group, "__getitem__", side_effect=Group.__getitem__, autospec=True |
| 2891 | + ) as mock, |
| 2892 | + ): |
| 2893 | + ds.to_zarr(store, mode="w") |
| 2894 | + |
| 2895 | + # We expect this to request array metadata information, so call_count should be >= 1, |
| 2896 | + # At time of writing, 2 calls are made |
| 2897 | + xrds = xr.open_zarr(store) |
| 2898 | + call_count = mock.call_count |
| 2899 | + assert call_count > 0 |
| 2900 | + |
| 2901 | + # compute() requests array data, which should not trigger additional metadata requests |
| 2902 | + # we assert that the number of calls has not increased after fetchhing the array |
| 2903 | + xrds.test.compute(scheduler="sync") |
| 2904 | + assert mock.call_count == call_count |
| 2905 | + |
| 2906 | + |
2865 | 2907 | @requires_zarr
|
2866 | 2908 | @requires_fsspec
|
2867 | 2909 | def test_zarr_storage_options() -> None:
|
|
0 commit comments