@@ -55,6 +55,20 @@ def fake_info(path_, urlbase_, params=None, headers=None, model=None, auth_token
5555 return blosc2 .C2Array (path , urlbase = urlbase )
5656
5757
58+ def _make_persistent_lazyexpr (tmp_path ):
59+ a = blosc2 .asarray (np .arange (5 , dtype = np .int64 ), urlpath = tmp_path / "a.b2nd" , mode = "w" )
60+ b = blosc2 .asarray (np .arange (5 , dtype = np .int64 ) * 2 , urlpath = tmp_path / "b.b2nd" , mode = "w" )
61+ expr = blosc2 .lazyexpr ("a + b" , operands = {"a" : a , "b" : b })
62+ expected = np .arange (5 , dtype = np .int64 ) * 3
63+ return expr , expected
64+
65+
66+ def _make_in_memory_lazyexpr ():
67+ a = blosc2 .asarray (np .arange (5 , dtype = np .int64 ))
68+ b = blosc2 .asarray (np .arange (5 , dtype = np .int64 ) * 2 )
69+ return blosc2 .lazyexpr ("a + b" , operands = {"a" : a , "b" : b })
70+
71+
5872@pytest .mark .parametrize (
5973 ("contiguous" , "urlpath" ),
6074 [
@@ -260,6 +274,96 @@ def test_batchstore_msgpack_supports_c2array(monkeypatch):
260274 assert restored .auth_token is None
261275
262276
277+ def test_msgpack_supports_lazyexpr (tmp_path ):
278+ expr , expected = _make_persistent_lazyexpr (tmp_path )
279+
280+ payload = msgpack_packb ({"expr" : expr })
281+ restored = msgpack_unpackb (payload )["expr" ]
282+
283+ assert isinstance (restored , blosc2 .LazyExpr )
284+ np .testing .assert_array_equal (restored [:], expected )
285+
286+
287+ def test_batchstore_msgpack_supports_lazyexpr (tmp_path ):
288+ expr , expected = _make_persistent_lazyexpr (tmp_path )
289+
290+ barray = blosc2 .BatchStore (items_per_block = 2 )
291+ barray .append ([expr ])
292+
293+ restored = barray [0 ][0 ]
294+
295+ assert isinstance (restored , blosc2 .LazyExpr )
296+ np .testing .assert_array_equal (restored [:], expected )
297+
298+
299+ def test_msgpack_rejects_lazyexpr_with_in_memory_operands ():
300+ expr = _make_in_memory_lazyexpr ()
301+
302+ with pytest .raises (ValueError , match = "stored on disk/network" ):
303+ msgpack_packb ({"expr" : expr })
304+
305+
306+ def test_batchstore_msgpack_rejects_lazyexpr_with_in_memory_operands ():
307+ expr = _make_in_memory_lazyexpr ()
308+
309+ barray = blosc2 .BatchStore (items_per_block = 2 )
310+ with pytest .raises (ValueError , match = "stored on disk/network" ):
311+ barray .append ([expr ])
312+
313+
314+ @pytest .mark .network
315+ def test_msgpack_supports_lazyexpr_with_c2array_operand (cat2_context , tmp_path ):
316+ path = "@public/expr/ds-1-2-linspace-float64-b2-(5,)d.b2nd"
317+ a = blosc2 .C2Array (path )
318+ a_values = np .asarray (a [:])
319+ b = blosc2 .asarray (a_values * 2 , urlpath = tmp_path / "b.b2nd" , mode = "w" )
320+ expr = blosc2 .lazyexpr ("a + b" , operands = {"a" : a , "b" : b })
321+
322+ restored = msgpack_unpackb (msgpack_packb ({"expr" : expr }))["expr" ]
323+
324+ assert isinstance (restored , blosc2 .LazyExpr )
325+ np .testing .assert_allclose (restored [:], a_values + b [:])
326+
327+
328+ @pytest .mark .network
329+ def test_batchstore_msgpack_supports_lazyexpr_with_c2array_operand (cat2_context , tmp_path ):
330+ path = "@public/expr/ds-1-2-linspace-float64-b2-(5,)d.b2nd"
331+ a = blosc2 .C2Array (path )
332+ a_values = np .asarray (a [:])
333+ b = blosc2 .asarray (a_values * 2 , urlpath = tmp_path / "b.b2nd" , mode = "w" )
334+ expr = blosc2 .lazyexpr ("a + b" , operands = {"a" : a , "b" : b })
335+
336+ barray = blosc2 .BatchStore (items_per_block = 2 )
337+ barray .append ([expr ])
338+ restored = barray [0 ][0 ]
339+
340+ assert isinstance (restored , blosc2 .LazyExpr )
341+ np .testing .assert_allclose (restored [:], a_values + b [:])
342+
343+
344+ @pytest .mark .xfail (
345+ strict = True , reason = "Structured LazyExpr urlpath operands do not preserve .b2z member offsets"
346+ )
347+ def test_msgpack_lazyexpr_with_b2z_operands (tmp_path ):
348+ store_path = tmp_path / "operands.b2z"
349+ ext_a = tmp_path / "a.b2nd"
350+ ext_b = tmp_path / "b.b2nd"
351+ expected = np .arange (5 , dtype = np .int64 ) * 3
352+
353+ a = blosc2 .asarray (np .arange (5 , dtype = np .int64 ), urlpath = str (ext_a ), mode = "w" )
354+ b = blosc2 .asarray (np .arange (5 , dtype = np .int64 ) * 2 , urlpath = str (ext_b ), mode = "w" )
355+ with blosc2 .DictStore (str (store_path ), mode = "w" , threshold = None ) as dstore :
356+ dstore ["/a" ] = a
357+ dstore ["/b" ] = b
358+
359+ with blosc2 .DictStore (str (store_path ), mode = "r" ) as dstore :
360+ expr = blosc2 .lazyexpr ("a + b" , operands = {"a" : dstore ["/a" ], "b" : dstore ["/b" ]})
361+ restored = msgpack_unpackb (msgpack_packb ({"expr" : expr }))["expr" ]
362+
363+ assert isinstance (restored , blosc2 .LazyExpr )
364+ np .testing .assert_array_equal (restored [:], expected )
365+
366+
263367@pytest .mark .network
264368def test_msgpack_roundtrip_c2array_network (cat2_context ):
265369 path = "@public/expr/ds-1-2-linspace-float64-b2-(5,)d.b2nd"
0 commit comments