File tree Expand file tree Collapse file tree 3 files changed +20
-1
lines changed Expand file tree Collapse file tree 3 files changed +20
-1
lines changed Original file line number Diff line number Diff line change
1
+ Suppress `FileNotFoundError ` when deleting non-existent keys in the `obstore ` adapter.
2
+
3
+ When writing empty chunks (i.e. chunks where all values are equal to the array's fill value) to a zarr array, zarr
4
+ will delete those chunks from the underlying store. For zarr arrays backed by the `obstore ` adapter, this will potentially
5
+ raise a `FileNotFoundError ` if the chunk doesn't already exist.
6
+ Since whether or not a delete of a non-existing object raises an error depends on the behavior of the underlying store,
7
+ suppressing the error in all cases results in consistent behavior across stores, and is also what `zarr ` seems to expect
8
+ from the store.
Original file line number Diff line number Diff line change @@ -181,7 +181,13 @@ async def delete(self, key: str) -> None:
181
181
import obstore as obs
182
182
183
183
self ._check_writable ()
184
- await obs .delete_async (self .store , key )
184
+
185
+ # Some obstore stores such as local filesystems, GCP and Azure raise an error
186
+ # when deleting a non-existent key, while others such as S3 and in-memory do
187
+ # not. We suppress the error to make the behavior consistent across all obstore
188
+ # stores. This is also in line with the behavior of the other Zarr store adapters.
189
+ with contextlib .suppress (FileNotFoundError ):
190
+ await obs .delete_async (self .store , key )
185
191
186
192
@property
187
193
def supports_partial_writes (self ) -> bool :
Original file line number Diff line number Diff line change @@ -349,6 +349,11 @@ async def test_delete_dir(self, store: S) -> None:
349
349
assert not await store .exists ("foo/zarr.json" )
350
350
assert not await store .exists ("foo/c/0" )
351
351
352
+ async def test_delete_nonexistent_key_does_not_raise (self , store : S ) -> None :
353
+ if not store .supports_deletes :
354
+ pytest .skip ("store does not support deletes" )
355
+ await store .delete ("nonexistent_key" )
356
+
352
357
async def test_is_empty (self , store : S ) -> None :
353
358
assert await store .is_empty ("" )
354
359
await self .set (
You can’t perform that action at this time.
0 commit comments