8
8
from nose .tools import assert_raises
9
9
import numpy as np
10
10
from numpy .testing import assert_array_equal
11
- from numcodecs import Zlib
11
+ from numcodecs import Zlib , Adler32
12
12
import pytest
13
13
14
14
@@ -182,111 +182,175 @@ def test_copy_store():
182
182
assert 'bar/qux' in dest
183
183
184
184
185
+ def check_copied_array (original , copied , without_attrs = False , expect_props = None ):
186
+
187
+ # setup
188
+ source_h5py = original .__module__ .startswith ('h5py.' )
189
+ dest_h5py = copied .__module__ .startswith ('h5py.' )
190
+ zarr_to_zarr = not (source_h5py or dest_h5py )
191
+ h5py_to_h5py = source_h5py and dest_h5py
192
+ zarr_to_h5py = not source_h5py and dest_h5py
193
+ h5py_to_zarr = source_h5py and not dest_h5py
194
+ if expect_props is None :
195
+ expect_props = dict ()
196
+ else :
197
+ expect_props = expect_props .copy ()
198
+
199
+ # common properties in zarr and h5py
200
+ for p in 'dtype' , 'shape' , 'chunks' :
201
+ expect_props .setdefault (p , getattr (original , p ))
202
+
203
+ # zarr-specific properties
204
+ if zarr_to_zarr :
205
+ for p in 'compressor' , 'filters' , 'order' , 'fill_value' :
206
+ expect_props .setdefault (p , getattr (original , p ))
207
+
208
+ # h5py-specific properties
209
+ if h5py_to_h5py :
210
+ for p in ('maxshape' , 'compression' , 'compression_opts' , 'shuffle' ,
211
+ 'scaleoffset' , 'fletcher32' , 'fillvalue' ):
212
+ expect_props .setdefault (p , getattr (original , p ))
213
+
214
+ # common properties with some name differences
215
+ if h5py_to_zarr :
216
+ expect_props .setdefault ('fill_value' , original .fillvalue )
217
+ if zarr_to_h5py :
218
+ expect_props .setdefault ('fillvalue' , original .fill_value )
219
+
220
+ # compare properties
221
+ for k , v in expect_props .items ():
222
+ assert v == getattr (copied , k )
223
+
224
+ # compare data
225
+ assert_array_equal (original [:], copied [:])
226
+
227
+ # compare attrs
228
+ if without_attrs :
229
+ for k in original .attrs .keys ():
230
+ assert k not in copied .attrs
231
+ else :
232
+ assert sorted (original .attrs .items ()) == sorted (copied .attrs .items ())
233
+
234
+
235
+ def check_copied_group (original , copied , without_attrs = False , expect_props = None ,
236
+ shallow = False ):
237
+
238
+ # setup
239
+ if expect_props is None :
240
+ expect_props = dict ()
241
+ else :
242
+ expect_props = expect_props .copy ()
243
+
244
+ # compare children
245
+ for k , v in original .items ():
246
+ if hasattr (v , 'shape' ):
247
+ assert k in copied
248
+ check_copied_array (v , copied [k ], without_attrs = without_attrs ,
249
+ expect_props = expect_props )
250
+ elif shallow :
251
+ assert k not in copied
252
+ else :
253
+ assert k in copied
254
+ check_copied_group (v , copied [k ], without_attrs = without_attrs ,
255
+ shallow = shallow , expect_props = expect_props )
256
+
257
+ # compare attrs
258
+ if without_attrs :
259
+ for k in original .attrs .keys ():
260
+ assert k not in copied .attrs
261
+ else :
262
+ assert sorted (original .attrs .items ()) == sorted (copied .attrs .items ())
263
+
264
+
185
265
def _test_copy (new_source , new_dest ):
186
266
187
267
source = new_source ()
268
+ dest = new_dest ()
269
+ # source_h5py = source.__module__.startswith('h5py.')
270
+ dest_h5py = dest .__module__ .startswith ('h5py.' )
271
+
272
+ # setup source
188
273
foo = source .create_group ('foo' )
189
274
foo .attrs ['experiment' ] = 'weird science'
190
275
baz = foo .create_dataset ('bar/baz' , data = np .arange (100 ), chunks = (50 ,))
191
276
baz .attrs ['units' ] = 'metres'
192
- spam = source .create_dataset ('spam' , data = np .arange (100 , 200 ), chunks = (30 ,))
277
+ source .create_dataset ('spam' , data = np .arange (100 , 200 ), chunks = (30 ,))
193
278
194
279
# copy array with default options
195
- dest = new_dest ()
196
280
copy (source ['foo/bar/baz' ], dest )
197
- a = dest ['baz' ] # defaults to use source name
198
- assert a .dtype == baz .dtype
199
- assert a .shape == baz .shape
200
- assert a .chunks == baz .chunks
201
- if hasattr (a , 'compressor' ) and hasattr (baz , 'compressor' ):
202
- assert a .compressor == baz .compressor
203
- assert_array_equal (a [:], baz [:])
204
- assert a .attrs ['units' ] == 'metres'
281
+ check_copied_array (source ['foo/bar/baz' ], dest ['baz' ])
205
282
206
283
# copy array with name
207
284
dest = new_dest ()
208
285
copy (source ['foo/bar/baz' ], dest , name = 'qux' )
209
286
assert 'baz' not in dest
210
- a = dest ['qux' ]
211
- assert a .dtype == baz .dtype
212
- assert a .shape == baz .shape
213
- assert a .chunks == baz .chunks
214
- if hasattr (a , 'compressor' ) and hasattr (baz , 'compressor' ):
215
- assert a .compressor == baz .compressor
216
- assert_array_equal (a [:], baz [:])
217
- assert a .attrs ['units' ] == 'metres'
287
+ check_copied_array (source ['foo/bar/baz' ], dest ['qux' ])
218
288
219
289
# copy array, provide creation options
220
290
dest = new_dest ()
221
291
compressor = Zlib (9 )
222
- if isinstance (dest , Group ):
223
- copy (source ['foo/bar/baz' ], dest , without_attrs = True , compressor = compressor ,
224
- chunks = True )
225
- else :
226
- copy (source ['foo/bar/baz' ], dest , without_attrs = True , compression = 'gzip' ,
227
- compression_opts = 9 , chunks = True )
228
- a = dest ['baz' ]
229
- assert a .dtype == baz .dtype
230
- assert a .shape == baz .shape
231
- assert a .chunks != baz .chunks # autochunking was requested
232
- if hasattr (a , 'compressor' ):
233
- assert compressor == a .compressor
234
- if hasattr (baz , 'compressor' ):
235
- assert a .compressor != baz .compressor
292
+ create_kws = dict (chunks = (10 ,))
293
+ if dest_h5py :
294
+ create_kws .update (compression = 'gzip' , compression_opts = 9 , shuffle = True ,
295
+ fletcher32 = True , fillvalue = 42 )
236
296
else :
237
- assert a .compression == 'gzip'
238
- assert a .compression_opts == 9
239
- assert_array_equal (a [:], baz [:])
240
- assert 'units' not in a .attrs
297
+ create_kws .update (compressor = compressor , fill_value = 42 , order = 'F' ,
298
+ filters = [Adler32 ()])
299
+ copy (source ['foo/bar/baz' ], dest , without_attrs = True , ** create_kws )
300
+ check_copied_array (source ['foo/bar/baz' ], dest ['baz' ], without_attrs = True ,
301
+ expect_props = create_kws )
302
+
303
+ # copy array, dest array in the way
304
+ dest = new_dest ()
305
+ dest .create_dataset ('baz' , shape = (10 ,))
306
+ with pytest .raises (ValueError ):
307
+ copy (source ['foo/bar/baz' ], dest )
308
+ assert (10 ,) == dest ['baz' ].shape
309
+ copy (source ['foo/bar/baz' ], dest , overwrite = True )
310
+ check_copied_array (source ['foo/bar/baz' ], dest ['baz' ])
311
+
312
+ # copy array, dest group in the way
313
+ dest = new_dest ()
314
+ dest .create_group ('baz' )
315
+ with pytest .raises (ValueError ):
316
+ copy (source ['foo/bar/baz' ], dest )
317
+ assert not hasattr (dest ['baz' ], 'shape' )
318
+ copy (source ['foo/bar/baz' ], dest , overwrite = True )
319
+ check_copied_array (source ['foo/bar/baz' ], dest ['baz' ])
241
320
242
321
# copy group, default options
243
322
dest = new_dest ()
244
323
copy (source ['foo' ], dest )
245
- g = dest ['foo' ] # defaults to use source name
246
- assert g .attrs ['experiment' ] == 'weird science'
247
- a = g ['bar/baz' ]
248
- assert a .dtype == baz .dtype
249
- assert a .shape == baz .shape
250
- assert a .chunks == baz .chunks
251
- if hasattr (a , 'compressor' ) and hasattr (baz , 'compressor' ):
252
- assert a .compressor == baz .compressor
253
- assert_array_equal (a [:], baz [:])
254
- assert a .attrs ['units' ] == 'metres'
324
+ check_copied_group (source ['foo' ], dest ['foo' ])
255
325
256
326
# copy group, non-default options
257
327
dest = new_dest ()
258
328
copy (source ['foo' ], dest , name = 'qux' , without_attrs = True )
259
329
assert 'foo' not in dest
260
- g = dest ['qux' ]
261
- assert 'experiment' not in g .attrs
262
- a = g ['bar/baz' ]
263
- assert a .dtype == baz .dtype
264
- assert a .shape == baz .shape
265
- assert a .chunks == baz .chunks
266
- if hasattr (a , 'compressor' ) and hasattr (baz , 'compressor' ):
267
- assert a .compressor == baz .compressor
268
- assert_array_equal (a [:], baz [:])
269
- assert 'units' not in a .attrs
330
+ check_copied_group (source ['foo' ], dest ['qux' ], without_attrs = True )
270
331
271
332
# copy group, shallow
272
333
dest = new_dest ()
273
334
copy (source , dest , name = 'eggs' , shallow = True )
274
- assert 'eggs' in dest
275
- eggs = dest ['eggs' ]
276
- assert 'spam' in eggs
277
- a = eggs ['spam' ]
278
- assert a .dtype == spam .dtype
279
- assert a .shape == spam .shape
280
- assert a .chunks == spam .chunks
281
- if hasattr (a , 'compressor' ) and hasattr (spam , 'compressor' ):
282
- assert a .compressor == spam .compressor
283
- assert_array_equal (a [:], spam [:])
284
- assert 'foo' not in eggs
285
- assert 'bar' not in eggs
286
-
287
-
288
- def test_copy_zarr_zarr ():
289
- # zarr -> zarr
335
+ check_copied_group (source , dest ['eggs' ], shallow = True )
336
+
337
+ # copy group, dest groups exist
338
+ dest = new_dest ()
339
+ dest .create_group ('foo/bar' )
340
+ copy (source ['foo' ], dest )
341
+ check_copied_group (source ['foo' ], dest ['foo' ])
342
+
343
+ # copy group, dest array in the way
344
+ dest = new_dest ()
345
+ dest .create_dataset ('foo/bar' , shape = (10 ,))
346
+ with pytest .raises (ValueError ):
347
+ copy (source ['foo' ], dest )
348
+ assert dest ['foo/bar' ].shape == (10 ,)
349
+ copy (source ['foo' ], dest , overwrite = True )
350
+ check_copied_group (source ['foo' ], dest ['foo' ])
351
+
352
+
353
+ def test_copy_zarr_to_zarr ():
290
354
_test_copy (group , group )
291
355
292
356
@@ -305,18 +369,15 @@ def temp_h5f():
305
369
306
370
307
371
@pytest .mark .skipif (not have_h5py , reason = 'h5py not installed' )
308
- def test_copy_h5py_zarr ():
309
- # h5py -> zarr
372
+ def test_copy_h5py_to_zarr ():
310
373
_test_copy (temp_h5f , group )
311
374
312
375
313
376
@pytest .mark .skipif (not have_h5py , reason = 'h5py not installed' )
314
- def test_copy_zarr_h5py ():
315
- # zarr -> h5py
377
+ def test_copy_zarr_to_h5py ():
316
378
_test_copy (group , temp_h5f )
317
379
318
380
319
381
@pytest .mark .skipif (not have_h5py , reason = 'h5py not installed' )
320
- def test_copy_h5py_h5py ():
321
- # zarr -> h5py
382
+ def test_copy_h5py_to_h5py ():
322
383
_test_copy (temp_h5f , temp_h5f )
0 commit comments