6
6
# License: AGPL
7
7
8
8
import logging
9
+ from contextlib import AbstractContextManager , nullcontext
9
10
from pathlib import Path
10
- from typing import Optional , Union
11
+ from typing import Any , Optional , Union
11
12
12
13
import pytest
14
+ from nibabel .filebasedimages import ImageFileError
13
15
from ruamel .yaml import YAML
14
16
15
17
import junifer .testing .registry # noqa: F401
16
18
from junifer .api import collect , list_elements , queue , reset , run
17
19
from junifer .datagrabber .base import BaseDataGrabber
18
20
from junifer .pipeline import PipelineComponentRegistry
21
+ from junifer .typing import Elements
19
22
20
23
21
24
# Configure YAML class
25
28
yaml .indent (mapping = 2 , sequence = 4 , offset = 2 )
26
29
27
30
31
+ # Kept for parametrizing
32
+ _datagrabber = {
33
+ "kind" : "PartlyCloudyTestingDataGrabber" ,
34
+ }
35
+ _bids_ses_datagrabber = {
36
+ "kind" : "PatternDataladDataGrabber" ,
37
+ "uri" : "https://gin.g-node.org/juaml/datalad-example-bids-ses" ,
38
+ "types" : ["T1w" , "BOLD" ],
39
+ "patterns" : {
40
+ "T1w" : {
41
+ "pattern" : (
42
+ "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz"
43
+ ),
44
+ "space" : "MNI152NLin6Asym" ,
45
+ },
46
+ "BOLD" : {
47
+ "pattern" : (
48
+ "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz"
49
+ ),
50
+ "space" : "MNI152NLin6Asym" ,
51
+ },
52
+ },
53
+ "replacements" : ["subject" , "session" ],
54
+ "rootdir" : "example_bids_ses" ,
55
+ }
56
+
57
+
28
58
@pytest .fixture
29
59
def datagrabber () -> dict [str , str ]:
30
60
"""Return a datagrabber as a dictionary."""
31
- return {
32
- "kind" : "PartlyCloudyTestingDataGrabber" ,
33
- }
61
+ return _datagrabber .copy ()
34
62
35
63
36
64
@pytest .fixture
@@ -60,11 +88,48 @@ def storage() -> dict[str, str]:
60
88
}
61
89
62
90
91
+ @pytest .mark .parametrize (
92
+ "datagrabber, element, expect" ,
93
+ [
94
+ (
95
+ _datagrabber ,
96
+ [("sub-01" ,)],
97
+ pytest .raises (RuntimeError , match = "element selectors are invalid" ),
98
+ ),
99
+ (
100
+ _datagrabber ,
101
+ ["sub-01" ],
102
+ nullcontext (),
103
+ ),
104
+ (
105
+ _bids_ses_datagrabber ,
106
+ ["sub-01" ],
107
+ pytest .raises (ImageFileError , match = "is not a gzip file" ),
108
+ ),
109
+ (
110
+ _bids_ses_datagrabber ,
111
+ [("sub-01" , "ses-01" )],
112
+ pytest .raises (ImageFileError , match = "is not a gzip file" ),
113
+ ),
114
+ (
115
+ _bids_ses_datagrabber ,
116
+ [("sub-01" , "ses-100" )],
117
+ pytest .raises (RuntimeError , match = "element selectors are invalid" ),
118
+ ),
119
+ (
120
+ _bids_ses_datagrabber ,
121
+ [("sub-100" , "ses-01" )],
122
+ pytest .raises (RuntimeError , match = "element selectors are invalid" ),
123
+ ),
124
+ ],
125
+ )
63
126
def test_run_single_element (
64
127
tmp_path : Path ,
65
- datagrabber : dict [str , str ],
128
+ datagrabber : dict [str , Any ],
66
129
markers : list [dict [str , str ]],
67
130
storage : dict [str , str ],
131
+ element : Elements ,
132
+ expect : AbstractContextManager ,
68
133
) -> None :
69
134
"""Test run function with single element.
70
135
@@ -78,21 +143,26 @@ def test_run_single_element(
78
143
Testing markers as list of dictionary.
79
144
storage : dict
80
145
Testing storage as dictionary.
146
+ element : list of str or tuple
147
+ The parametrized element.
148
+ expect : typing.ContextManager
149
+ The parametrized ContextManager object.
81
150
82
151
"""
83
152
# Set storage
84
153
storage ["uri" ] = str ((tmp_path / "out.sqlite" ).resolve ())
85
154
# Run operations
86
- run (
87
- workdir = tmp_path ,
88
- datagrabber = datagrabber ,
89
- markers = markers ,
90
- storage = storage ,
91
- elements = [("sub-01" ,)],
92
- )
93
- # Check files
94
- files = list (tmp_path .glob ("*.sqlite" ))
95
- assert len (files ) == 1
155
+ with expect :
156
+ run (
157
+ workdir = tmp_path ,
158
+ datagrabber = datagrabber ,
159
+ markers = markers ,
160
+ storage = storage ,
161
+ elements = element ,
162
+ )
163
+ # Check files
164
+ files = list (tmp_path .glob ("*.sqlite" ))
165
+ assert len (files ) == 1
96
166
97
167
98
168
def test_run_single_element_with_preprocessing (
@@ -128,18 +198,30 @@ def test_run_single_element_with_preprocessing(
128
198
"kind" : "fMRIPrepConfoundRemover" ,
129
199
}
130
200
],
131
- elements = [( "sub-01" ,) ],
201
+ elements = ["sub-01" ],
132
202
)
133
203
# Check files
134
204
files = list (tmp_path .glob ("*.sqlite" ))
135
205
assert len (files ) == 1
136
206
137
207
208
+ @pytest .mark .parametrize (
209
+ "element, expect" ,
210
+ [
211
+ (
212
+ [("sub-01" ,), ("sub-03" ,)],
213
+ pytest .raises (RuntimeError , match = "element selectors are invalid" ),
214
+ ),
215
+ (["sub-01" , "sub-03" ], nullcontext ()),
216
+ ],
217
+ )
138
218
def test_run_multi_element_multi_output (
139
219
tmp_path : Path ,
140
220
datagrabber : dict [str , str ],
141
221
markers : list [dict [str , str ]],
142
222
storage : dict [str , str ],
223
+ element : Elements ,
224
+ expect : AbstractContextManager ,
143
225
) -> None :
144
226
"""Test run function with multi element and multi output.
145
227
@@ -153,22 +235,27 @@ def test_run_multi_element_multi_output(
153
235
Testing markers as list of dictionary.
154
236
storage : dict
155
237
Testing storage as dictionary.
238
+ element : list of str or tuple
239
+ The parametrized element.
240
+ expect : typing.ContextManager
241
+ The parametrized ContextManager object.
156
242
157
243
"""
158
244
# Set storage
159
245
storage ["uri" ] = str ((tmp_path / "out.sqlite" ).resolve ())
160
246
storage ["single_output" ] = False # type: ignore
161
247
# Run operations
162
- run (
163
- workdir = tmp_path ,
164
- datagrabber = datagrabber ,
165
- markers = markers ,
166
- storage = storage ,
167
- elements = [("sub-01" ,), ("sub-03" ,)],
168
- )
169
- # Check files
170
- files = list (tmp_path .glob ("*.sqlite" ))
171
- assert len (files ) == 2
248
+ with expect :
249
+ run (
250
+ workdir = tmp_path ,
251
+ datagrabber = datagrabber ,
252
+ markers = markers ,
253
+ storage = storage ,
254
+ elements = element ,
255
+ )
256
+ # Check files
257
+ files = list (tmp_path .glob ("*.sqlite" ))
258
+ assert len (files ) == 2
172
259
173
260
174
261
def test_run_multi_element_single_output (
@@ -200,7 +287,7 @@ def test_run_multi_element_single_output(
200
287
datagrabber = datagrabber ,
201
288
markers = markers ,
202
289
storage = storage ,
203
- elements = [( "sub-01" ,), ( "sub-03" ,) ],
290
+ elements = ["sub-01" , "sub-03" ],
204
291
)
205
292
# Check files
206
293
files = list (tmp_path .glob ("*.sqlite" ))
@@ -569,7 +656,7 @@ def test_reset_run(
569
656
datagrabber = datagrabber ,
570
657
markers = markers ,
571
658
storage = storage ,
572
- elements = [( "sub-01" ,) ],
659
+ elements = ["sub-01" ],
573
660
)
574
661
# Reset operation
575
662
reset (config = {"storage" : storage })
0 commit comments