Skip to content

Commit b9c3c02

Browse files
authored
Merge pull request #645 from andrewfulton9/fsspec_indexer_error
2 parents 848dcd3 + 959fbcf commit b9c3c02

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

docs/release.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ This release will be the first release of Zarr not supporting Python 3.5.
1010
* End Python 3.5 support.
1111
By :user:`Chris Barnes <clbarnes>`; :issue:`602`.
1212

13+
* Add `Array` tests for FSStore.
14+
By :user:`Andrew Fulton <andrewfulton9>`; :issue: `644`.
15+
1316
2.5.0
1417
-----
1518

requirements_dev_optional.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ pytest-doctestplus==0.4.0
1919
pytest-remotedata==0.3.2
2020
h5py==2.10.0
2121
s3fs==0.5.1; python_version > '3.6'
22-
fsspec==0.8.3; python_version > '3.6'
22+
fsspec==0.8.4; python_version > '3.6'
2323
moto>=1.3.14; python_version > '3.6'
2424
flask

zarr/core.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,8 @@ def _get_selection(self, indexer, out=None, fields=None):
10201020
check_array_shape('out', out, out_shape)
10211021

10221022
# iterate over chunks
1023-
if not hasattr(self.chunk_store, "getitems"):
1023+
if not hasattr(self.chunk_store, "getitems") or \
1024+
any(map(lambda x: x == 0, self.shape)):
10241025
# sequentially get one key at a time from storage
10251026
for chunk_coords, chunk_selection, out_selection in indexer:
10261027

@@ -1535,7 +1536,8 @@ def _set_selection(self, indexer, value, fields=None):
15351536
check_array_shape('value', value, sel_shape)
15361537

15371538
# iterate over chunks in range
1538-
if not hasattr(self.store, "setitems") or self._synchronizer is not None:
1539+
if not hasattr(self.store, "setitems") or self._synchronizer is not None \
1540+
or any(map(lambda x: x == 0, self.shape)):
15391541
# iterative approach
15401542
for chunk_coords, chunk_selection, out_selection in indexer:
15411543

zarr/storage.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,9 @@ def rmdir(self, path=None):
11131113
raise ReadOnlyError()
11141114
store_path = self.dir_path(path)
11151115
if self.fs.isdir(store_path):
1116-
self.fs.rm(store_path, recursive=True)
1116+
# sometimes doesn't delete on first try with S3
1117+
while self.fs.exists(store_path):
1118+
self.fs.rm(store_path, recursive=True)
11171119

11181120
def getsize(self, path=None):
11191121
store_path = self.dir_path(path)

zarr/tests/test_core.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
from zarr.n5 import N5Store, n5_keywords
2121
from zarr.storage import (ABSStore, DBMStore, DirectoryStore, LMDBStore,
2222
LRUStoreCache, NestedDirectoryStore, SQLiteStore,
23-
atexit_rmglob, atexit_rmtree, init_array, init_group)
23+
FSStore, atexit_rmglob, atexit_rmtree, init_array,
24+
init_group
25+
)
2426
from zarr.util import buffer_size
25-
from zarr.tests.util import skip_test_env_var
27+
from zarr.tests.util import skip_test_env_var, have_fsspec
2628

2729

2830
# noinspection PyMethodMayBeStatic
@@ -2366,3 +2368,42 @@ def create_array(read_only=False, **kwargs):
23662368
def test_store_has_bytes_values(self):
23672369
# skip as the cache has no control over how the store provides values
23682370
pass
2371+
2372+
2373+
@pytest.mark.skipif(have_fsspec is False, reason="needs fsspec")
2374+
class TestArrayWithFSStore(TestArray):
2375+
2376+
@staticmethod
2377+
def create_array(read_only=False, **kwargs):
2378+
path = mkdtemp()
2379+
atexit.register(shutil.rmtree, path)
2380+
store = FSStore(path)
2381+
cache_metadata = kwargs.pop('cache_metadata', True)
2382+
cache_attrs = kwargs.pop('cache_attrs', True)
2383+
kwargs.setdefault('compressor', Blosc())
2384+
init_array(store, **kwargs)
2385+
return Array(store, read_only=read_only, cache_metadata=cache_metadata,
2386+
cache_attrs=cache_attrs)
2387+
2388+
def test_hexdigest(self):
2389+
# Check basic 1-D array
2390+
z = self.create_array(shape=(1050,), chunks=100, dtype='<i4')
2391+
assert 'f710da18d45d38d4aaf2afd7fb822fdd73d02957' == z.hexdigest()
2392+
2393+
# Check basic 1-D array with different type
2394+
z = self.create_array(shape=(1050,), chunks=100, dtype='<f4')
2395+
assert '1437428e69754b1e1a38bd7fc9e43669577620db' == z.hexdigest()
2396+
2397+
# Check basic 2-D array
2398+
z = self.create_array(shape=(20, 35,), chunks=10, dtype='<i4')
2399+
assert '6c530b6b9d73e108cc5ee7b6be3d552cc994bdbe' == z.hexdigest()
2400+
2401+
# Check basic 1-D array with some data
2402+
z = self.create_array(shape=(1050,), chunks=100, dtype='<i4')
2403+
z[200:400] = np.arange(200, 400, dtype='i4')
2404+
assert '4c0a76fb1222498e09dcd92f7f9221d6cea8b40e' == z.hexdigest()
2405+
2406+
# Check basic 1-D array with attributes
2407+
z = self.create_array(shape=(1050,), chunks=100, dtype='<i4')
2408+
z.attrs['foo'] = 'bar'
2409+
assert '05b0663ffe1785f38d3a459dec17e57a18f254af' == z.hexdigest()

0 commit comments

Comments
 (0)