Skip to content

Commit 760bf19

Browse files
authored
FSStore: key_separator fix (#699)
* key_separator: failing tests * key_separator: fix handling of meta keys This rebases and cleans a fix from Martin's original PR. Two new test methods fail without it and pass with since keys for meta-files like `.zarray` were being converted into `/zarray`. see: martindurant@5795bc7
1 parent e37713f commit 760bf19

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

zarr/storage.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,8 @@ class FSStore(MutableMapping):
10201020
storage_options : passed to the fsspec implementation
10211021
"""
10221022

1023+
_META_KEYS = (attrs_key, group_meta_key, array_meta_key)
1024+
10231025
def __init__(self, url, normalize_keys=True, key_separator='.',
10241026
mode='w',
10251027
exceptions=(KeyError, PermissionError, IOError),
@@ -1039,7 +1041,11 @@ def _normalize_key(self, key):
10391041
key = normalize_storage_path(key).lstrip('/')
10401042
if key:
10411043
*bits, end = key.split('/')
1042-
key = '/'.join(bits + [end.replace('.', self.key_separator)])
1044+
1045+
if end not in FSStore._META_KEYS:
1046+
end = end.replace('.', self.key_separator)
1047+
key = '/'.join(bits + [end])
1048+
10431049
return key.lower() if self.normalize_keys else key
10441050

10451051
def getitems(self, keys, **kwargs):

zarr/tests/test_storage.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -863,12 +863,27 @@ def mock_walker_no_slash(_path):
863863
@pytest.mark.skipif(have_fsspec is False, reason="needs fsspec")
864864
class TestFSStore(StoreTests, unittest.TestCase):
865865

866-
def create_store(self, normalize_keys=False):
866+
def create_store(self, normalize_keys=False, key_separator="."):
867867
path = tempfile.mkdtemp()
868868
atexit.register(atexit_rmtree, path)
869-
store = FSStore(path, normalize_keys=normalize_keys)
869+
store = FSStore(
870+
path,
871+
normalize_keys=normalize_keys,
872+
key_separator=key_separator)
870873
return store
871874

875+
def test_key_separator(self):
876+
for x in (".", "/"):
877+
store = self.create_store(key_separator=x)
878+
norm = store._normalize_key
879+
assert ".zarray" == norm(".zarray")
880+
assert ".zarray" == norm("/.zarray")
881+
assert ".zgroup" == norm("/.zgroup")
882+
assert "group/.zarray" == norm("group/.zarray")
883+
assert "group/.zgroup" == norm("group/.zgroup")
884+
assert "group/.zarray" == norm("/group/.zarray")
885+
assert "group/.zgroup" == norm("/group/.zgroup")
886+
872887
def test_complex(self):
873888
path1 = tempfile.mkdtemp()
874889
path2 = tempfile.mkdtemp()
@@ -1183,13 +1198,27 @@ def test_filters(self):
11831198
@pytest.mark.skipif(have_fsspec is False, reason="needs fsspec")
11841199
class TestNestedFSStore(TestNestedDirectoryStore):
11851200

1186-
def create_store(self, normalize_keys=False):
1187-
path = tempfile.mkdtemp()
1201+
def create_store(self, normalize_keys=False, path=None):
1202+
if path is None:
1203+
path = tempfile.mkdtemp()
11881204
atexit.register(atexit_rmtree, path)
11891205
store = FSStore(path, normalize_keys=normalize_keys,
11901206
key_separator='/', auto_mkdir=True)
11911207
return store
11921208

1209+
def test_numbered_groups(self):
1210+
import zarr
1211+
1212+
# Create an array
1213+
store = self.create_store()
1214+
group = zarr.group(store=store)
1215+
arr = group.create_dataset('0', shape=(10, 10))
1216+
arr[1] = 1
1217+
1218+
# Read it back
1219+
store = self.create_store(path=store.path)
1220+
zarr.open_group(store.path)["0"]
1221+
11931222

11941223
class TestTempStore(StoreTests, unittest.TestCase):
11951224

0 commit comments

Comments
 (0)