Skip to content

Commit fa0362c

Browse files
committed
Add new (and persistent) meta layers for DictStore and TreeStore. Fixes #546.
1 parent a3d237e commit fa0362c

6 files changed

Lines changed: 26 additions & 4 deletions

File tree

src/blosc2/dict_store.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
class DictStore:
2424
"""
2525
Directory-based storage for compressed data using Blosc2.
26+
2627
Manages arrays in a directory (.b2d) or zip (.b2z) format.
2728
2829
Supports the following types:
@@ -102,6 +103,7 @@ def __init__(
102103
threshold: int | None = 2**13,
103104
*,
104105
mmap_mode: str | None = None,
106+
_storage_meta: dict | None = None,
105107
):
106108
"""
107109
See :class:`DictStore` for full documentation of parameters.
@@ -123,6 +125,12 @@ def __init__(
123125
self.dparams = dparams or blosc2.DParams()
124126
self.storage = storage or blosc2.Storage()
125127

128+
if _storage_meta:
129+
self.storage.meta = _storage_meta
130+
else:
131+
# Mark this storage as a b2dict object
132+
self.storage.meta = {"b2dict": {"version": 1}}
133+
126134
self.offsets = {}
127135
self.map_tree = {}
128136
self._temp_dir_obj = None
@@ -187,6 +195,7 @@ def _init_read_mode(self, dparams: blosc2.DParams | None = None):
187195
self._update_map_tree()
188196

189197
self._estore = EmbedStore(_from_schunk=schunk)
198+
self.storage.meta = self._estore.storage.meta
190199

191200
def _init_write_append_mode(
192201
self,
@@ -208,6 +217,7 @@ def _init_write_append_mode(
208217
cparams=cparams,
209218
dparams=dparams,
210219
storage=storage,
220+
meta=self.storage.meta,
211221
)
212222
self._update_map_tree()
213223

src/blosc2/embed_store.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def __init__(
8181
_from_schunk: SChunk | None = None,
8282
*,
8383
mmap_mode: str | None = None,
84+
meta: dict | None = None,
8485
):
8586
"""Initialize EmbedStore."""
8687

@@ -100,6 +101,8 @@ def __init__(
100101
self.dparams = _from_schunk.dparams
101102
self.mode = mode
102103
self._store = _from_schunk
104+
self.storage = blosc2.Storage()
105+
self.storage.meta = _from_schunk.meta
103106
self._load_metadata()
104107
return
105108

@@ -119,14 +122,14 @@ def __init__(
119122

120123
if mode in ("r", "a") and urlpath:
121124
self._store = blosc2.blosc2_ext.open(urlpath, mode=mode, offset=0, mmap_mode=mmap_mode)
125+
self.storage.meta = self._store.meta
122126
self._load_metadata()
123127
return
124128

125129
_cparams = copy.deepcopy(self.cparams)
126130
_cparams.typesize = 1 # ensure typesize is set to 1 for byte storage
127131
_storage = self.storage
128-
# Mark this storage as a b2embed object
129-
_storage.meta = {"b2embed": {"version": 1}}
132+
_storage.meta = meta if meta is not None else {"b2embed": {"version": 1}}
130133
if self._schunk_store:
131134
self._store = blosc2.SChunk(
132135
chunksize=chunksize,

src/blosc2/tree_store.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class TreeStore(DictStore):
149149
"""
150150

151151
# For some reason, we had to revert the explicit parametrisation of the
152-
# constructor to make benchmarks wrok fine again.
152+
# constructor to make benchmarks working again.
153153
def __init__(self, *args, _from_parent_store=None, **kwargs):
154154
"""Initialize TreeStore with subtree support.
155155
@@ -159,7 +159,9 @@ def __init__(self, *args, _from_parent_store=None, **kwargs):
159159
# This is a subtree view, copy state from parent
160160
self.__dict__.update(_from_parent_store.__dict__)
161161
else:
162-
super().__init__(*args, **kwargs)
162+
# Call initialization and mark this storage as a b2tree object
163+
super().__init__(*args, **kwargs, _storage_meta={"b2tree": {"version": 1}})
164+
163165
self.subtree_path = "" # Empty string means full tree
164166

165167
def _is_vlmeta_key(self, key: str) -> bool:

tests/test_dict_store.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def populated_dict_store(request):
4848

4949
def test_basic_dstore(populated_dict_store):
5050
dstore, path = populated_dict_store
51+
assert "b2dict" in dstore.storage.meta
5152
assert set(dstore.keys()) == {"/node1", "/node2", "/dir1/node3"}
5253
assert np.all(dstore["/node1"][:] == np.array([1, 2, 3]))
5354
assert np.all(dstore["/node2"][:] == np.ones(2))
@@ -64,6 +65,7 @@ def test_basic_dstore(populated_dict_store):
6465
# Persist and reopen
6566
dstore.close()
6667
with DictStore(path, mode="r") as dstore_read:
68+
assert "b2dict" in dstore_read.storage.meta
6769
keys = set(dstore_read.keys())
6870
assert "/node2" in keys
6971
assert "/dir1/node3" in keys

tests/test_embed_store.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def populate_nodes(cleanup_files):
4242
def test_basic(populate_nodes):
4343
estore = populate_nodes
4444

45+
assert "b2embed" in estore.storage.meta
4546
assert set(estore.keys()) == {"/node1", "/node2", "/node3"}
4647
assert np.all(estore["/node1"][:] == np.array([1, 2, 3]))
4748
assert np.all(estore["/node2"][:] == np.arange(3))
@@ -51,6 +52,7 @@ def test_basic(populate_nodes):
5152
assert "/node1" not in estore
5253

5354
estore_read = blosc2.EmbedStore(urlpath="test_estore.b2e", mode="r")
55+
assert "b2embed" in estore_read.storage.meta
5456
assert set(estore_read.keys()) == {"/node2", "/node3"}
5557
for value in estore_read.values():
5658
assert hasattr(value, "shape")

tests/test_tree_store.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def test_basic_tree_store(populated_tree_store):
4949
"""Test basic TreeStore functionality."""
5050
tstore, _ = populated_tree_store
5151

52+
assert "b2tree" in tstore.storage.meta
53+
5254
# Test key existence - should include both leaf and structural nodes
5355
expected_keys = {
5456
"/child0/data",
@@ -450,6 +452,7 @@ def test_treestore_vlmeta_basic_and_bulk(storage_type):
450452

451453
# Reopen in read-only to check persistence and read-only protection
452454
with TreeStore(path, mode="r") as tstore:
455+
assert "b2tree" in tstore.storage.meta
453456
assert tstore.vlmeta["author"] == "blosc2"
454457
assert tstore.vlmeta["version"] == 1
455458
assert tstore.vlmeta["shape"] == (3, 2)

0 commit comments

Comments
 (0)