Completed
Push — master ( 6ce243...b034e1 )
by Alexandre M.
52s
created

hansel.tests.test_has_files()   F

Complexity

Conditions 10

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 10
dl 0
loc 24
rs 3.5556

How to fix   Complexity   

Complexity

Complex classes like hansel.tests.test_has_files() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
3
# vi: set ft=python sts=4 ts=4 sw=4 et:
4
5
6
import pytest
7
8
import os
9
import os.path  as op
10
import shutil
11
from   copy     import copy
12
from   pathlib  import Path
13
from   tempfile import TemporaryDirectory
14
15
from   six      import string_types
16
from   hansel   import Crumb, mktree
17
from   hansel.utils import ParameterGrid
18
19
20
BASE_DIR = op.expanduser('~/data/cobre')
21
22
23
@pytest.fixture
24
def crumb(request):
25
26
    crumb = Crumb("{base_dir}/raw/{subject_id}/{session_id}/{modality}/{image}")
27
28
    def fin():
29
        print("teardown crumb")
30
31
    request.addfinalizer(fin)
32
    return crumb  # provide the fixture value
33
34
35
@pytest.fixture
36
def tmp_crumb(request):
37
    from tempfile import TemporaryDirectory
38
39
    crumb = Crumb("{base_dir}/raw/{subject_id}/{session_id}/{modality}/{image}")
40
    base_dir = TemporaryDirectory(prefix='crumbtest_')
41
    crumb2 = crumb.replace(base_dir=base_dir.name)
42
43
    def fin():
44
        print("teardown tmp_crumb")
45
    #    shutil.rmtree(base_dir.name)
46
    #    #os.removedirs(base_dir.name)
47
48
    request.addfinalizer(fin)
49
    return crumb2  # provide the fixture value
50
51
52
def test__get_path(tmp_crumb):
53
    pytest.raises(TypeError, tmp_crumb._get_path, {})
54
    pytest.raises(TypeError, tmp_crumb._get_path, [])
55
56
    assert tmp_crumb._get_path(tmp_crumb) == tmp_crumb._path
57
58
59
def test_path_property(crumb):
60
61
    assert crumb.path == crumb._path
62
63
    base_dir = BASE_DIR
64
    crumb2 = crumb.replace(base_dir=base_dir)
65
66
    assert crumb2.path == crumb2._path
67
    assert crumb.path != crumb2._path
68
    assert crumb._argidx != crumb2._argidx
69
70
    crumb.path = crumb2.path
71
72
    assert crumb.path == crumb.path
73
    assert crumb._argidx == crumb2._argidx
74
75
76
def test_replace_and_setitem(crumb):
77
    base_dir = BASE_DIR
78
    crumb.path = op.join(crumb.path, '{hansel}', '{gretel}')
79
80
    # use replace
81
    crumb2 = crumb.replace(base_dir=base_dir)
82
83
    assert crumb2._path == op.join(base_dir, crumb._path.replace('{base_dir}/', ''))
84
    assert 'base_dir' not in crumb2._argidx
85
86
    # use setitem
87
    crumb3 = crumb.copy(crumb)
88
    crumb3['base_dir'] = base_dir
89
90
    assert crumb3._replace1(**dict()) == crumb3._path
91
    assert crumb3._replace2(**dict()) == crumb3._path
92
93
    assert crumb3 is not crumb2
94
    assert crumb3 == crumb2
95
    assert crumb3._path == crumb2._path
96
    assert 'base_dir' not in crumb3._argidx
97
98
    assert crumb3.replace(**{})._path == crumb3._path
99
100
    pytest.raises(KeyError, crumb2.replace,     grimm='brothers')
101
    pytest.raises(KeyError, crumb2._replace1,   grimm='brothers')
102
    pytest.raises(KeyError, crumb2._replace2,   grimm='brothers')
103
    pytest.raises(KeyError, crumb2.__setitem__, 'grimm', 'brothers')
104
105
106
def test_firstarg(crumb):
107
    an, ai = crumb._firstarg()
108
    assert an == 'base_dir'
109
    assert ai == 0
110
111
    base_dir = BASE_DIR
112
    crumb2 = crumb.replace(base_dir=base_dir)
113
114
    an, ai = crumb2._firstarg()
115
    assert an == 'subject_id'
116
    assert ai == len(base_dir.split(op.sep)) + 1
117
118
119
def test_lastarg(crumb):
120
    an, ai = crumb._lastarg()
121
    assert an == 'image'
122
    assert ai == len(crumb._path_split()) - 1
123
124
    base_dir = BASE_DIR
125
    crumb2 = crumb.replace(base_dir=base_dir)
126
127
    an, ai = crumb2._lastarg()
128
    assert an == 'image'
129
    assert ai == len(crumb2._path_split()) - 1
130
131
132
def test_isabs(crumb):
133
    base_dir = BASE_DIR
134
    crumb2 = crumb.replace(base_dir=base_dir)
135
136
    assert not crumb.isabs()
137
    assert crumb2.isabs()
138
139
140
def test_argidx_order(crumb):
141
    base_dir = BASE_DIR
142
    crumb2 = crumb.replace(base_dir=base_dir)
143
144
    assert sorted(list(crumb._argidx.values()))  == list(crumb._argidx.values())
145
    assert sorted(list(crumb2._argidx.values())) == list(crumb2._argidx.values())
146
147
148
def test_abspath(crumb):
149
    crumb2 = crumb.abspath(first_is_basedir=False)
150
    assert crumb2._path == op.join(op.abspath(op.curdir), crumb._path)
151
    assert crumb is not crumb2
152
    assert crumb2.isabs()
153
    assert crumb != crumb2
154
    assert 'base_dir' in crumb2._argidx
155
156
    crumb3 = crumb.abspath(first_is_basedir=True)
157
    assert crumb3._path == op.join(op.abspath(op.curdir), crumb._path.replace('{base_dir}/', ''))
158
    assert crumb is not crumb3
159
    assert crumb3.isabs()
160
161
    assert crumb3 != crumb2
162
163
    assert Crumb(op.expanduser('~'))._abspath() == op.expanduser('~')
164
165
    base_dir = BASE_DIR
166
    crumb2 = crumb.replace(base_dir=base_dir)
167
    crumbc = crumb2.abspath(first_is_basedir=False)
168
    assert crumbc == crumb2
169
    assert crumbc is not crumb2
170
171
172
def test_copy(crumb):
173
    copy = Crumb.copy(crumb)
174
    assert crumb is not copy
175
    assert crumb == copy
176
177
    pytest.raises(TypeError, crumb.copy, {})
178
179
180
def test_equal_no_copy(crumb):
181
    crumb2 = crumb
182
    assert crumb2 == crumb
183
184
    crumb2._path += '/'
185
    assert crumb2 == crumb
186
187
    crumb2.path == op.join(crumb._path, '{test}')
188
    assert crumb2 == crumb
189
190
    crumb2._argidx['hansel'] = []
191
    assert crumb2 == crumb
192
193
194
def test_equal_copy(crumb):
195
    crumb2 = Crumb.copy(crumb)
196
    assert crumb2 == crumb
197
198
    crumb2._path += '/'
199
    assert crumb2 != crumb
200
201
    crumb2._path == op.join(crumb._path, '{test}')
202
    assert crumb2 != crumb
203
204
    crumb2._argidx['hansel'] = []
205
    assert crumb2 != crumb
206
207
208
def test_split(crumb):
209
    splt = crumb.split()
210
    for s in splt:
211
        if op.isdir(s):
212
            assert op.exists(s)
213
        else:
214
            assert Crumb._is_crumb_arg(s) or isinstance(s, string_types)
215
216
217
def test_is_valid_a_bit(crumb):
218
    assert Crumb.is_valid(crumb)
219
220
    crumb_path = crumb._path
221
    crumb_path = crumb_path[:3] + Crumb._arg_start_sym + crumb_path[3:-1]
222
223
    assert isinstance(Crumb.from_path(Path(crumb_path)), Path)
224
    pytest.raises(ValueError, Crumb.from_path, crumb_path)
225
    pytest.raises(TypeError, crumb.from_path, {})
226
227
    assert not Crumb.is_valid(crumb_path)
228
    assert Crumb.is_valid(op.expanduser('~'))
229
230
    crumb._path = crumb_path
231
    pytest.raises(ValueError, crumb._check)
232
    pytest.raises(ValueError, crumb.isabs)
233
    pytest.raises(ValueError, crumb.abspath)
234
235
236
def test_arg_name(crumb):
237
    pytest.raises(ValueError, crumb._arg_name, 'hansel')
238
    assert not crumb._is_crumb_arg(Path(op.expanduser('~')))
239
240
241
def test_has_crumbs(crumb):
242
    assert Crumb.has_crumbs(crumb)
243
244
    assert not Crumb.has_crumbs('')
245
    assert not Crumb.has_crumbs('/home/hansel/.config')
246
247
248
def test_str(crumb):
249
    assert crumb._path == str(crumb)
250
251
252
def test_ls_raises():
253
    crumb = Crumb(op.join('{home}', '{user_folder}'))
254
255
    pytest.raises(ValueError, crumb.ls, 'hansel')
256
257
    pytest.raises(NotImplementedError, crumb.ls, 'home')
258
259
    pytest.raises(ValueError, crumb.ls, 'user',
260
                  make_crumbs=True, fullpath=False)
261
262
263
def test_ls_and_getitem():
264
    base_dir = op.expanduser('~')
265
    crumb = Crumb(op.join(base_dir, '{user_folder}'))
266
267
    lst = crumb.ls('user_folder',
268
                   fullpath     = False,
269
                   duplicates   = True,
270
                   make_crumbs  = False,
271
                   check_exists = False)
272
    assert set(lst) == set(os.listdir(base_dir))
273
274
    crumb = Crumb(op.join(base_dir, '{user_folder}', '{files}'))
275
    lst = crumb.ls('user_folder',
276
                   fullpath     = False,
277
                   duplicates   = True,
278
                   make_crumbs  = False,
279
                   check_exists = False)
280
    assert set(lst) == set([d for d in os.listdir(base_dir) if op.isdir(op.join(base_dir, d))])
281
282
    flst = crumb.ls('user_folder',
283
                    fullpath     = True,
284
                    duplicates   = True,
285
                    make_crumbs  = False,
286
                    check_exists = False)
287
    assert all([isinstance(f, string_types) for f in flst])
288
    assert all([not op.exists(f) for f in flst])
289
290
    flst = crumb.ls('files',
291
                    fullpath     = True,
292
                    duplicates   = True,
293
                    make_crumbs  = False,
294
                    check_exists = False)
295
    assert all([isinstance(f, string_types) for f in flst])
296
    assert all([op.exists(f) or op.islink(f) for f in flst])
297
298
    flst = crumb.ls('files',
299
                    fullpath     = True,
300
                    duplicates   = True,
301
                    make_crumbs  = True,
302
                    check_exists = False)
303
    assert all([isinstance(f, Path) for f in flst])
304
    assert all([f.exists() or f.is_symlink() for f in flst])
305
306
    flst1 = crumb.ls('files',
307
                     fullpath     = False,
308
                     duplicates   = False,
309
                     make_crumbs  = False,
310
                     check_exists = True)
311
    flst2 = crumb['files']
312
    assert all([isinstance(f, str) for f in flst1])
313
    assert flst1 == flst2
314
315
    flst = crumb.ls('user_folder',
316
                     fullpath     = True,
317
                     duplicates   = True,
318
                     make_crumbs  = True,
319
                     check_exists = False)
320
    assert all([isinstance(f, Crumb) for f in flst])
321
    # check if all crumbs exist
322
    assert all([c.exists() for c in flst])
323
324
    #TODO: missing test ls with duplicates=False
325
326
327
def test_ls3():
328
    from glob import glob
329
    base_dir = op.expanduser('~')
330
    files = [d for d in glob(op.join(base_dir, '*')) if op.isfile(d)]
331
    crumb = Crumb(op.join(files[0], '{user_folder}', '{files}'))
332
    lst = crumb.ls('user_folder')
333
    assert not lst
334
335
    lst = crumb.ls('files')
336
    assert not lst
337
338
339
def test_rem_deps(crumb):
340
341
    values = copy(crumb._argidx)
342
    assert not crumb._remaining_deps(values)
343
344
    del values['base_dir']
345
    assert crumb._remaining_deps(values) == ['base_dir']
346
347
    del values['subject_id']
348
    assert crumb._remaining_deps(values) == ['subject_id', 'base_dir']
349
350
    values = copy(crumb._argidx)
351
    del values['base_dir']
352
    del values['modality']
353
    assert crumb._remaining_deps(values) == ['modality', 'base_dir']
354
355
    values = copy(crumb._argidx)
356
    del values['image']
357
    del values['modality']
358
    assert not crumb._remaining_deps(values)
359
360
361
# def test_remdeps2(tmp_crumb):
362
#     values_dict = {'session_id': ['session_' + str(i) for i in range(2)],
363
#                    'subject_id': ['subj_' + str(i) for i in range(3)],
364
#                    'modality':   ['anat', 'rest', 'pet'],
365
#                    'image':      ['mprage.nii', 'rest.nii', 'pet.nii'],
366
#                    }
367
#
368
#     del values_dict['subject_id']
369
#     del values_dict['image']
370
#     values_map = list(ParameterGrid(values_dict))
371
#
372
#     assert tmp_crumb._remaining_deps(['image']) == ['modality', 'base_dir']
373
374
375
def test_touch(tmp_crumb):
376
    assert not op.exists(tmp_crumb.split()[0])
377
    path = tmp_crumb.touch()
378
    assert path == tmp_crumb.split()[0]
379
    assert op.exists(path)
380
381
382
def test__touch():
383
    base_dir = TemporaryDirectory()
384
    path = op.join(base_dir.name, 'hansel')
385
386
    assert not op.exists(path)
387
388
    nupath = Crumb._touch(path)
389
    assert nupath == path
390
    assert op.exists(nupath)
391
392
    pytest.raises(IOError, Crumb._touch, nupath, exist_ok=False)
393
394
    #pytest.raises(IOError, Crumb._touch, path + '\\', exist_ok=False)
395
396
397
def test_arg_values(tmp_crumb):
398
    # the most of _arg_values is being tested in test_ls
399
    pytest.raises(ValueError, tmp_crumb._arg_values, 'session_id')
400
401
402
def test_exists(tmp_crumb):
403
    assert not op.exists(tmp_crumb.split()[0])
404
405
    values_map = {'session_id': ['session_' + str(i) for i in range(2)],
406
                  'subject_id': ['subj_' + str(i) for i in range(3)]}
407
408
    pytest.raises(IOError, tmp_crumb._arg_values, 'subject_id')
409
    assert not tmp_crumb.exists()
410
411
    _ = mktree(tmp_crumb, list(ParameterGrid(values_map)))
412
413
    assert tmp_crumb.exists()
414
415
    assert not Crumb._split_exists('/_/asdfasdfasdf?/{hansel}')
416
417
418
def test_contains(tmp_crumb):
419
    assert 'modality'   in tmp_crumb
420
    assert 'subject_id' in tmp_crumb
421
    assert 'image'      in tmp_crumb
422
    assert 'raw'    not in tmp_crumb
423
424
    tmp_crumb['image'] = 'image'
425
426
    assert 'image' not in tmp_crumb
427
428
429
def test_ls_with_check(tmp_crumb):
430
    assert not op.exists(tmp_crumb._path)
431
432
    values_dict = {'session_id': ['session_' + str(i) for i in range(2)],
433
                   'subject_id': ['subj_' + str(i) for i in range(3)],
434
                   'modality':   ['anat'],
435
                   'image':      ['mprage1.nii', 'mprage2.nii', 'mprage3.nii'],
436
                   }
437
438
    paths = mktree(tmp_crumb, list(ParameterGrid(values_dict)))
439
440
    assert op.exists(tmp_crumb.split()[0])
441
442
    assert all([op.exists(p) for p in paths])
443
444
    images = tmp_crumb.ls('image',
445
                          fullpath     = True,
446
                          make_crumbs  = True,
447
                          duplicates   = False,
448
                          check_exists = True)
449
450
    modalities = tmp_crumb.ls('modality',
451
                              fullpath     = True,
452
                              make_crumbs  = True,
453
                              duplicates   = False,
454
                              check_exists = True)
455
456
    assert all([img.exists() for img in images])
457
    assert all([mod.exists() for mod in modalities])
458
459
    images[0].rmdir()
460
461
    images2 = tmp_crumb.ls('image',
462
                           fullpath     = True,
463
                           make_crumbs  = True,
464
                           duplicates   = False,
465
                           check_exists = True)
466
467
    assert images != images2
468
    assert len(images) == len(images2) + 1
469
    assert not all([img.exists() for img in images])
470
    assert     all([img.exists() for img in images2])
471
472
    images[1].rmdir()
473
    images[2].rmdir()
474
475
    images2 = tmp_crumb.ls('image',
476
                           fullpath     = True,
477
                           make_crumbs  = True,
478
                           duplicates   = False,
479
                           check_exists = True)
480
481
    assert not all([img.exists() for img in images])
482
    assert     all([img.exists() for img in images2])
483
484
    modalities2 = tmp_crumb.ls('modality',
485
                               fullpath     = True,
486
                               make_crumbs  = True,
487
                               duplicates   = False,
488
                               check_exists = True)
489
490
    str_modalities2 = tmp_crumb.ls('modality',
491
                                   fullpath     = True,
492
                                   make_crumbs  = False,
493
                                   duplicates   = False,
494
                                   check_exists = True)
495
496
    assert images != images2
497
    assert len(images) == len(images2) + 3
498
499
    assert modalities == modalities2
500
    assert all([mod.exists() for mod in modalities])
501
    assert all([mod.exists() for mod in modalities2])
502
    assert all([mod._path == smod for mod, smod in zip(modalities2, str_modalities2)])
503
504
    os.removedirs(modalities2[0].split()[0])
505
506
    modalities3 = tmp_crumb.ls('modality',
507
                               fullpath     = True,
508
                               make_crumbs  = True,
509
                               duplicates   = False,
510
                               check_exists = True)
511
512
    assert modalities2 != modalities3
513
    assert not all([mod.exists() for mod in modalities2])
514
    assert     all([mod.exists() for mod in modalities3])
515
516
    pytest.raises(IOError, modalities2[0].__getitem__, 'image')
517
518
    img_crumb = tmp_crumb.replace(image='mprage1.nii')
519
    img_crumb['modality'] = 'anat'
520
521
    assert img_crumb['session_id'].count('session_1') > img_crumb['session_id'].count('session_0')
522
523
    img_crumb['session_id'] = 'session_0'
524
525
    assert 'subj_0' not in img_crumb['subject_id']
526
527
528
def test_has_files(tmp_crumb):
529
    assert not op.exists(tmp_crumb._path)
530
531
    assert not tmp_crumb.has_files()
532
533
    values_dict = {'session_id': ['session_' + str(i) for i in range(2)],
534
                   'subject_id': ['subj_' + str(i) for i in range(3)],
535
                   'modality':   ['anat'],
536
                   'image':      ['mprage1.nii', 'mprage2.nii', 'mprage3.nii'],
537
                   }
538
539
    paths = mktree(tmp_crumb, list(ParameterGrid(values_dict)))
540
541
    assert op.exists(tmp_crumb.split()[0])
542
543
    assert not tmp_crumb.has_files()
544
545
    pa = Path(paths[0])
546
    pa.rmdir()
547
    pa.touch()
548
549
    assert pa.exists()
550
    assert pa.is_file()
551
    assert tmp_crumb.has_files()
552
553
554
def test_repr(crumb):
555
    assert crumb.__repr__() == 'Crumb("{base_dir}/raw/{subject_id}/{session_id}/{modality}/{image}")'
556
557
558
if __name__ == '__main__':
559
    import os.path as op
560
    from tempfile import TemporaryDirectory
561
    from hansel import Crumb
562
    from hansel.utils import ParameterGrid
563
564
    # crumb = Crumb("{base_dir}/raw/{subject_id}/{session_id}/{modality}/{image}")
565
    # base_dir = TemporaryDirectory()
566
    # crumb2 = crumb.replace(base_dir=base_dir.name)
567
    #
568
    # values_map = {'session_id': ['session_' + str(i) for i in range(2)],
569
    #               'subject_id': ['subj_' + str(i) for i in range(3)],
570
    #               'modality':   ['anat', 'rest', 'pet'],
571
    #               }
572
    #
573
    # nupaths = crumb2.mktree(list(ParameterGrid(values_map)))
574
    #
575
    # assert all([op.exists(npath) for npath in nupaths])
576
    #
577
    # anat_crumb = crumb2.replace(modality='anat')
578
    #
579
    # anat_crumb.ls('subject_id')
580
581
582
    base_dir = op.expanduser('~/data/cobre')
583
    crumb = Crumb("{base_dir}/raw/{subject_id}/{session_id}/{modality}/{image}")
584
585
    crumb['base_dir'] = base_dir
586
    crumb['session_id'] = 'session_1'
587
588
    rest_crumb = Crumb.copy(crumb)
589
    anat_crumb = Crumb.copy(crumb)
590
591
    rest_crumb['modality'] = 'rest_1'
592
    rest_crumb['image'] = 'rest.nii.gz'
593
594
    anat_crumb['modality'] = 'anat_1'
595
    anat_crumb['image'] = 'mprage.nii.gz'
596