Skip to content

Commit f6e3d61

Browse files
authored
check type of attribute keys (#1066)
* check type of attribute keys * introduce deprecation cycle * fix typo * stringify keys * cleanup * do not cover except
1 parent ea7bb11 commit f6e3d61

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

zarr/attrs.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from collections.abc import MutableMapping
23

34
from zarr._storage.store import Store, StoreV3
@@ -128,6 +129,27 @@ def put(self, d):
128129
self._write_op(self._put_nosync, dict(attributes=d))
129130

130131
def _put_nosync(self, d):
132+
133+
d_to_check = d if self._version == 2 else d["attributes"]
134+
if not all(isinstance(item, str) for item in d_to_check):
135+
# TODO: Raise an error for non-string keys
136+
# raise TypeError("attribute keys must be strings")
137+
warnings.warn(
138+
"only attribute keys of type 'string' will be allowed in the future",
139+
DeprecationWarning,
140+
stacklevel=2
141+
)
142+
143+
try:
144+
d_to_check = {str(k): v for k, v in d_to_check.items()}
145+
except TypeError as ex: # pragma: no cover
146+
raise TypeError("attribute keys can not be stringified") from ex
147+
148+
if self._version == 2:
149+
d = d_to_check
150+
else:
151+
d["attributes"] = d_to_check
152+
131153
if self._version == 2:
132154
self.store[self.key] = json_dumps(d)
133155
if self.cache:

zarr/tests/test_attrs.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,18 @@ def test_caching_off(self, zarr_version):
268268
get_cnt = 10 if zarr_version == 2 else 12
269269
assert get_cnt == store.counter['__getitem__', attrs_key]
270270
assert 3 == store.counter['__setitem__', attrs_key]
271+
272+
def test_wrong_keys(self, zarr_version):
273+
store = _init_store(zarr_version)
274+
a = self.init_attributes(store, zarr_version=zarr_version)
275+
276+
warning_msg = "only attribute keys of type 'string' will be allowed in the future"
277+
278+
with pytest.warns(DeprecationWarning, match=warning_msg):
279+
a[1] = "foo"
280+
281+
with pytest.warns(DeprecationWarning, match=warning_msg):
282+
a.put({1: "foo"})
283+
284+
with pytest.warns(DeprecationWarning, match=warning_msg):
285+
a.update({1: "foo"})

0 commit comments

Comments
 (0)