junifer 0.0.6.dev277__py3-none-any.whl → 0.0.6.dev299__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
junifer/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.0.6.dev277'
16
- __version_tuple__ = version_tuple = (0, 0, 6, 'dev277')
15
+ __version__ = version = '0.0.6.dev299'
16
+ __version_tuple__ = version_tuple = (0, 0, 6, 'dev299')
junifer/api/functions.py CHANGED
@@ -21,7 +21,7 @@ from ..pipeline import (
21
21
  from ..preprocess import BasePreprocessor
22
22
  from ..storage import BaseFeatureStorage
23
23
  from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
24
- from ..utils import logger, raise_error, yaml
24
+ from ..utils import logger, raise_error, warn_with_log, yaml
25
25
 
26
26
 
27
27
  __all__ = ["collect", "list_elements", "queue", "reset", "run"]
@@ -116,18 +116,18 @@ def _get_storage(storage_config: dict) -> StorageLike:
116
116
 
117
117
 
118
118
  def run(
119
- workdir: Union[str, Path],
119
+ workdir: Union[str, Path, dict],
120
120
  datagrabber: dict,
121
121
  markers: list[dict],
122
122
  storage: dict,
123
123
  preprocessors: Optional[list[dict]] = None,
124
- elements: Union[str, list[Union[str, tuple]], tuple, None] = None,
124
+ elements: Optional[list[tuple[str, ...]]] = None,
125
125
  ) -> None:
126
126
  """Run the pipeline on the selected element.
127
127
 
128
128
  Parameters
129
129
  ----------
130
- workdir : str or pathlib.Path
130
+ workdir : str or pathlib.Path or dict
131
131
  Directory where the pipeline will be executed.
132
132
  datagrabber : dict
133
133
  DataGrabber to use. Must have a key ``kind`` with the kind of
@@ -143,23 +143,38 @@ def run(
143
143
  Storage to use. Must have a key ``kind`` with the kind of
144
144
  storage to use. All other keys are passed to the storage
145
145
  constructor.
146
- preprocessors : list of dict, optional
146
+ preprocessors : list of dict or None, optional
147
147
  List of preprocessors to use. Each preprocessor is a dict with at
148
148
  least a key ``kind`` specifying the preprocessor to use. All other keys
149
149
  are passed to the preprocessor constructor (default None).
150
- elements : str or tuple or list of str or tuple, optional
150
+ elements : list of tuple or None, optional
151
151
  Element(s) to process. Will be used to index the DataGrabber
152
152
  (default None).
153
153
 
154
+ Raises
155
+ ------
156
+ ValueError
157
+ If ``workdir.cleanup=False`` when ``len(elements) > 1``.
158
+
154
159
  """
155
- # Convert str to Path
156
- if isinstance(workdir, str):
157
- workdir = Path(workdir)
158
- # Initiate working directory manager
159
- WorkDirManager(workdir)
160
+ # Conditional to handle workdir config
161
+ if isinstance(workdir, (str, Path)):
162
+ if isinstance(workdir, str):
163
+ workdir = {"workdir": Path(workdir), "cleanup": True}
164
+ else:
165
+ workdir = {"workdir": workdir, "cleanup": True}
166
+ elif isinstance(workdir, dict):
167
+ workdir["workdir"] = workdir.pop("path")
160
168
 
161
- if not isinstance(elements, list) and elements is not None:
162
- elements = [elements]
169
+ # Initiate working directory manager with correct variation
170
+ if not workdir["cleanup"]:
171
+ if elements is None or len(elements) > 1:
172
+ raise_error(
173
+ "Cannot disable `workdir.cleanup` as "
174
+ f"{len(elements) if elements is not None else 'all'} "
175
+ "elements will be processed"
176
+ )
177
+ WorkDirManager(**workdir)
163
178
 
164
179
  # Get datagrabber to use
165
180
  datagrabber_object = _get_datagrabber(datagrabber.copy())
@@ -228,7 +243,7 @@ def queue(
228
243
  kind: str,
229
244
  jobname: str = "junifer_job",
230
245
  overwrite: bool = False,
231
- elements: Union[str, list[Union[str, tuple]], tuple, None] = None,
246
+ elements: Optional[list[tuple[str, ...]]] = None,
232
247
  **kwargs: Union[str, int, bool, dict, tuple, list],
233
248
  ) -> None:
234
249
  """Queue a job to be executed later.
@@ -243,7 +258,7 @@ def queue(
243
258
  The name of the job (default "junifer_job").
244
259
  overwrite : bool, optional
245
260
  Whether to overwrite if job directory already exists (default False).
246
- elements : str or tuple or list of str or tuple, optional
261
+ elements : list of tuple or None, optional
247
262
  Element(s) to process. Will be used to index the DataGrabber
248
263
  (default None).
249
264
  **kwargs : dict
@@ -282,6 +297,16 @@ def queue(
282
297
  shutil.rmtree(jobdir)
283
298
  jobdir.mkdir(exist_ok=True, parents=True)
284
299
 
300
+ # Check workdir config
301
+ if "workdir" in config:
302
+ if isinstance(config["workdir"], dict):
303
+ if not config["workdir"]["cleanup"]:
304
+ warn_with_log(
305
+ "`workdir.cleanup` will be set to True when queueing"
306
+ )
307
+ # Set cleanup
308
+ config["workdir"]["cleanup"] = True
309
+
285
310
  # Load modules
286
311
  if "with" in config:
287
312
  to_load = config["with"]
@@ -381,7 +406,7 @@ def reset(config: dict) -> None:
381
406
 
382
407
  def list_elements(
383
408
  datagrabber: dict,
384
- elements: Union[str, list[Union[str, tuple]], tuple, None] = None,
409
+ elements: Optional[list[tuple[str, ...]]] = None,
385
410
  ) -> str:
386
411
  """List elements of the datagrabber filtered using `elements`.
387
412
 
@@ -391,7 +416,7 @@ def list_elements(
391
416
  DataGrabber to index. Must have a key ``kind`` with the kind of
392
417
  DataGrabber to use. All other keys are passed to the DataGrabber
393
418
  constructor.
394
- elements : str or tuple or list of str or tuple, optional
419
+ elements : list of tuple or None, optional
395
420
  Element(s) to filter using. Will be used to index the DataGrabber
396
421
  (default None).
397
422
 
@@ -88,7 +88,7 @@ def test_run_single_element(
88
88
  datagrabber=datagrabber,
89
89
  markers=markers,
90
90
  storage=storage,
91
- elements=["sub-01"],
91
+ elements=[("sub-01",)],
92
92
  )
93
93
  # Check files
94
94
  files = list(tmp_path.glob("*.sqlite"))
@@ -116,7 +116,7 @@ def test_run_single_element_with_preprocessing(
116
116
  storage["uri"] = str((tmp_path / "out.sqlite").resolve())
117
117
  # Run operations
118
118
  run(
119
- workdir=tmp_path,
119
+ workdir={"path": tmp_path, "cleanup": False},
120
120
  datagrabber={
121
121
  "kind": "PartlyCloudyTestingDataGrabber",
122
122
  "reduce_confounds": False,
@@ -128,7 +128,7 @@ def test_run_single_element_with_preprocessing(
128
128
  "kind": "fMRIPrepConfoundRemover",
129
129
  }
130
130
  ],
131
- elements=["sub-01"],
131
+ elements=[("sub-01",)],
132
132
  )
133
133
  # Check files
134
134
  files = list(tmp_path.glob("*.sqlite"))
@@ -164,7 +164,7 @@ def test_run_multi_element_multi_output(
164
164
  datagrabber=datagrabber,
165
165
  markers=markers,
166
166
  storage=storage,
167
- elements=["sub-01", "sub-03"],
167
+ elements=[("sub-01",), ("sub-03",)],
168
168
  )
169
169
  # Check files
170
170
  files = list(tmp_path.glob("*.sqlite"))
@@ -200,7 +200,7 @@ def test_run_multi_element_single_output(
200
200
  datagrabber=datagrabber,
201
201
  markers=markers,
202
202
  storage=storage,
203
- elements=["sub-01", "sub-03"],
203
+ elements=[("sub-01",), ("sub-03",)],
204
204
  )
205
205
  # Check files
206
206
  files = list(tmp_path.glob("*.sqlite"))
@@ -287,7 +287,10 @@ def test_queue_correct_yaml_config(
287
287
  queue(
288
288
  config={
289
289
  "with": "junifer.testing.registry",
290
- "workdir": str(tmp_path.resolve()),
290
+ "workdir": {
291
+ "path": str(tmp_path.resolve()),
292
+ "cleanup": True,
293
+ },
291
294
  "datagrabber": datagrabber,
292
295
  "markers": markers,
293
296
  "storage": storage,
@@ -342,7 +345,7 @@ def test_queue_invalid_job_queue(
342
345
  with monkeypatch.context() as m:
343
346
  m.chdir(tmp_path)
344
347
  queue(
345
- config={"elements": ["sub-001"]},
348
+ config={"elements": [("sub-001",)]},
346
349
  kind="ABC",
347
350
  )
348
351
 
@@ -366,13 +369,13 @@ def test_queue_assets_disallow_overwrite(
366
369
  m.chdir(tmp_path)
367
370
  # First generate assets
368
371
  queue(
369
- config={"elements": ["sub-001"]},
372
+ config={"elements": [("sub-001",)]},
370
373
  kind="HTCondor",
371
374
  jobname="prevent_overwrite",
372
375
  )
373
376
  # Re-run to trigger error
374
377
  queue(
375
- config={"elements": ["sub-001"]},
378
+ config={"elements": [("sub-001",)]},
376
379
  kind="HTCondor",
377
380
  jobname="prevent_overwrite",
378
381
  )
@@ -399,14 +402,14 @@ def test_queue_assets_allow_overwrite(
399
402
  m.chdir(tmp_path)
400
403
  # First generate assets
401
404
  queue(
402
- config={"elements": ["sub-001"]},
405
+ config={"elements": [("sub-001",)]},
403
406
  kind="HTCondor",
404
407
  jobname="allow_overwrite",
405
408
  )
406
409
  with caplog.at_level(logging.INFO):
407
410
  # Re-run to overwrite
408
411
  queue(
409
- config={"elements": ["sub-001"]},
412
+ config={"elements": [("sub-001",)]},
410
413
  kind="HTCondor",
411
414
  jobname="allow_overwrite",
412
415
  overwrite=True,
@@ -448,10 +451,16 @@ def test_queue_with_imports(
448
451
  (tmp_path / "a.py").touch()
449
452
  with caplog.at_level(logging.DEBUG):
450
453
  queue(
451
- config={"with": with_},
454
+ config={
455
+ "with": with_,
456
+ "workdir": {
457
+ "path": str(tmp_path.resolve()),
458
+ "cleanup": False,
459
+ },
460
+ },
452
461
  kind="HTCondor",
453
462
  jobname="with_import_check",
454
- elements="sub-001",
463
+ elements=[("sub-001",)],
455
464
  )
456
465
  assert "Copying" in caplog.text
457
466
  assert "Queue done" in caplog.text
@@ -465,10 +474,8 @@ def test_queue_with_imports(
465
474
  @pytest.mark.parametrize(
466
475
  "elements",
467
476
  [
468
- "sub-001",
469
- ["sub-001"],
470
- ["sub-001", "sub-002"],
471
- ("sub-001", "ses-001"),
477
+ [("sub-001",)],
478
+ [("sub-001",), ("sub-002",)],
472
479
  [("sub-001", "ses-001")],
473
480
  [("sub-001", "ses-001"), ("sub-001", "ses-002")],
474
481
  ],
@@ -477,7 +484,7 @@ def test_queue_with_elements(
477
484
  tmp_path: Path,
478
485
  monkeypatch: pytest.MonkeyPatch,
479
486
  caplog: pytest.LogCaptureFixture,
480
- elements: Union[str, list[Union[str, tuple[str]]], tuple[str]],
487
+ elements: list[tuple[str, ...]],
481
488
  ) -> None:
482
489
  """Test queue with elements.
483
490
 
@@ -489,7 +496,7 @@ def test_queue_with_elements(
489
496
  The pytest.MonkeyPatch object.
490
497
  caplog : pytest.LogCaptureFixture
491
498
  The pytest.LogCaptureFixture object.
492
- elements : str of list of str
499
+ elements : list of tuple
493
500
  The parametrized elements for the queue.
494
501
 
495
502
  """
@@ -562,7 +569,7 @@ def test_reset_run(
562
569
  datagrabber=datagrabber,
563
570
  markers=markers,
564
571
  storage=storage,
565
- elements=["sub-01"],
572
+ elements=[("sub-01",)],
566
573
  )
567
574
  # Reset operation
568
575
  reset(config={"storage": storage})
@@ -642,13 +649,13 @@ def test_reset_queue(
642
649
  @pytest.mark.parametrize(
643
650
  "elements",
644
651
  [
645
- ["sub-01"],
652
+ [("sub-01",)],
646
653
  None,
647
654
  ],
648
655
  )
649
656
  def test_list_elements(
650
657
  datagrabber: dict[str, str],
651
- elements: Optional[list[str]],
658
+ elements: Optional[list[tuple[str, ...]]],
652
659
  ) -> None:
653
660
  """Test elements listing.
654
661
 
junifer/cli/cli.py CHANGED
@@ -117,15 +117,16 @@ def run(
117
117
  filepath : click.Path
118
118
  The filepath to the configuration file.
119
119
  element : tuple of str
120
- The element to operate on.
120
+ The element(s) to operate on.
121
121
  verbose : click.Choice
122
122
  The verbosity level: warning, info or debug (default "info").
123
123
 
124
124
  """
125
+ # Setup logging
125
126
  configure_logging(level=verbose)
126
127
  # TODO(synchon): add validation
127
128
  # Parse YAML
128
- config = parse_yaml(filepath) # type: ignore
129
+ config = parse_yaml(filepath)
129
130
  # Retrieve working directory
130
131
  workdir = config["workdir"]
131
132
  # Fetch datagrabber
@@ -179,9 +180,12 @@ def collect(filepath: click.Path, verbose: Union[str, int]) -> None:
179
180
  The verbosity level: warning, info or debug (default "info").
180
181
 
181
182
  """
183
+ # Setup logging
182
184
  configure_logging(level=verbose)
183
185
  # TODO: add validation
184
- config = parse_yaml(filepath) # type: ignore
186
+ # Parse YAML
187
+ config = parse_yaml(filepath)
188
+ # Fetch storage
185
189
  storage = config["storage"]
186
190
  # Perform operation
187
191
  cli_func.collect(storage=storage)
@@ -206,7 +210,7 @@ def collect(filepath: click.Path, verbose: Union[str, int]) -> None:
206
210
  )
207
211
  def queue(
208
212
  filepath: click.Path,
209
- element: str,
213
+ element: tuple[str],
210
214
  overwrite: bool,
211
215
  submit: bool,
212
216
  verbose: Union[str, int],
@@ -219,8 +223,8 @@ def queue(
219
223
  ----------
220
224
  filepath : click.Path
221
225
  The filepath to the configuration file.
222
- element : str
223
- The element to operate using.
226
+ element : tuple of str
227
+ The element(s) to operate on.
224
228
  overwrite : bool
225
229
  Whether to overwrite existing directory.
226
230
  submit : bool
@@ -228,15 +232,26 @@ def queue(
228
232
  verbose : click.Choice
229
233
  The verbosity level: warning, info or debug (default "info").
230
234
 
235
+ Raises
236
+ ------
237
+ ValueError
238
+ If no ``queue`` section is found in the YAML.
239
+
231
240
  """
241
+ # Setup logging
232
242
  configure_logging(level=verbose)
233
243
  # TODO: add validation
244
+ # Parse YAML
234
245
  config = parse_yaml(filepath) # type: ignore
235
- elements = parse_elements(element, config)
246
+ # Check queue section
236
247
  if "queue" not in config:
237
248
  raise_error(f"No queue configuration found in {filepath}.")
249
+ # Parse elements
250
+ elements = parse_elements(element, config)
251
+ # Separate out queue section
238
252
  queue_config = config.pop("queue")
239
253
  kind = queue_config.pop("kind")
254
+ # Perform operation
240
255
  cli_func.queue(
241
256
  config=config,
242
257
  kind=kind,
@@ -366,6 +381,7 @@ def reset(
366
381
  The verbosity level: warning, info or debug (default "info").
367
382
 
368
383
  """
384
+ # Setup logging
369
385
  configure_logging(level=verbose)
370
386
  # Parse YAML
371
387
  config = parse_yaml(filepath)
@@ -408,7 +424,7 @@ def list_elements(
408
424
  filepath : click.Path
409
425
  The filepath to the configuration file.
410
426
  element : tuple of str
411
- The element to operate on.
427
+ The element(s) to operate on.
412
428
  output_file : click.Path or None
413
429
  The path to write the output to. If not None, writing to
414
430
  stdout is not performed.
@@ -416,9 +432,10 @@ def list_elements(
416
432
  The verbosity level: warning, info or debug (default "info").
417
433
 
418
434
  """
435
+ # Setup logging
419
436
  configure_logging(level=verbose)
420
437
  # Parse YAML
421
- config = parse_yaml(filepath) # type: ignore
438
+ config = parse_yaml(filepath)
422
439
  # Fetch datagrabber
423
440
  datagrabber = config["datagrabber"]
424
441
  # Parse elements
junifer/cli/parser.py CHANGED
@@ -140,7 +140,9 @@ def parse_yaml(filepath: Union[str, Path]) -> dict: # noqa: C901
140
140
  return contents
141
141
 
142
142
 
143
- def parse_elements(element: tuple[str], config: dict) -> Union[list, None]:
143
+ def parse_elements(
144
+ element: tuple[str, ...], config: dict
145
+ ) -> Union[list[tuple[str, ...]], None]:
144
146
  """Parse elements from cli.
145
147
 
146
148
  Parameters
@@ -170,7 +172,7 @@ def parse_elements(element: tuple[str], config: dict) -> Union[list, None]:
170
172
  """
171
173
  logger.debug(f"Parsing elements: {element}")
172
174
  # Early return None to continue with all elements
173
- if len(element) == 0:
175
+ if not element:
174
176
  return None
175
177
  # Check if the element is a file for single element;
176
178
  # if yes, then parse elements from it
@@ -17,7 +17,7 @@ from datalad.support.exceptions import IncompleteResultsError
17
17
  from datalad.support.gitrepo import GitRepo
18
18
 
19
19
  from ..pipeline import WorkDirManager
20
- from ..utils import logger, raise_error, warn_with_log
20
+ from ..utils import config, logger, raise_error, warn_with_log
21
21
  from .base import BaseDataGrabber
22
22
 
23
23
 
@@ -143,27 +143,49 @@ class DataladDataGrabber(BaseDataGrabber):
143
143
  """
144
144
  return super().datadir / self._rootdir
145
145
 
146
- def _get_dataset_id_remote(self) -> str:
146
+ def _get_dataset_id_remote(self) -> tuple[str, bool]:
147
147
  """Get the dataset ID from the remote.
148
148
 
149
149
  Returns
150
150
  -------
151
151
  str
152
152
  The dataset ID.
153
+ bool
154
+ Whether the dataset is dirty.
155
+
156
+ Raises
157
+ ------
158
+ ValueError
159
+ If the dataset ID cannot be obtained from the remote.
153
160
 
154
161
  """
155
162
  remote_id = None
163
+ is_dirty = False
156
164
  with tempfile.TemporaryDirectory() as tmpdir:
157
- logger.debug(f"Querying {self.uri} for dataset ID")
158
- repo = GitRepo.clone(
159
- self.uri, path=tmpdir, clone_options=["-n", "--depth=1"]
165
+ if not config.get("datagrabber.skipidcheck", False):
166
+ logger.debug(f"Querying {self.uri} for dataset ID")
167
+ repo = GitRepo.clone(
168
+ self.uri, path=tmpdir, clone_options=["-n", "--depth=1"]
169
+ )
170
+ repo.checkout(name=".datalad/config", options=["HEAD"])
171
+ remote_id = repo.config.get("datalad.dataset.id", None)
172
+ logger.debug(f"Got remote dataset ID = {remote_id}")
173
+
174
+ if not config.get("datagrabber.skipdirtycheck", False):
175
+ is_dirty = repo.dirty
176
+ else:
177
+ logger.debug("Skipping dirty check")
178
+ is_dirty = False
179
+ else:
180
+ logger.debug("Skipping dataset ID check")
181
+ remote_id = self._dataset.id
182
+ is_dirty = False
183
+ logger.debug(
184
+ f"Remote dataset is {'' if is_dirty else 'not'} dirty"
160
185
  )
161
- repo.checkout(name=".datalad/config", options=["HEAD"])
162
- remote_id = repo.config.get("datalad.dataset.id", None)
163
- logger.debug(f"Got remote dataset ID = {remote_id}")
164
186
  if remote_id is None:
165
187
  raise_error("Could not get dataset ID from remote")
166
- return remote_id
188
+ return remote_id, is_dirty
167
189
 
168
190
  def _dataset_get(self, out: dict) -> dict:
169
191
  """Get the dataset found from the path in ``out``.
@@ -178,6 +200,11 @@ class DataladDataGrabber(BaseDataGrabber):
178
200
  dict
179
201
  The unmodified input dictionary.
180
202
 
203
+ Raises
204
+ ------
205
+ datalad.support.exceptions.IncompleteResultsError
206
+ If there is a datalad-related problem while fetching data.
207
+
181
208
  """
182
209
  to_get = []
183
210
  for type_val in out.values():
@@ -230,6 +257,8 @@ class DataladDataGrabber(BaseDataGrabber):
230
257
  ------
231
258
  ValueError
232
259
  If the dataset is already installed but with a different ID.
260
+ datalad.support.exceptions.IncompleteResultsError
261
+ If there is a datalad-related problem while cloning dataset.
233
262
 
234
263
  """
235
264
  isinstalled = dl.Dataset(self._datadir).is_installed()
@@ -238,23 +267,23 @@ class DataladDataGrabber(BaseDataGrabber):
238
267
  self._got_files = []
239
268
  self._dataset: dl.Dataset = dl.Dataset(self._datadir)
240
269
 
241
- remote_id = self._get_dataset_id_remote()
270
+ # Check if dataset is already installed with a different ID
271
+ remote_id, is_dirty = self._get_dataset_id_remote()
242
272
  if remote_id != self._dataset.id:
243
273
  raise_error(
244
274
  "Dataset already installed but with a different "
245
275
  f"ID: {self._dataset.id} (local) != {remote_id} (remote)"
246
276
  )
247
277
 
248
- # Check for dirty datasets:
249
- status = self._dataset.status()
250
- if any(x["state"] != "clean" for x in status):
251
- self.datalad_dirty = True
278
+ # Conditional reporting on dataset dirtiness
279
+ self.datalad_dirty = is_dirty
280
+ if self.datalad_dirty:
252
281
  warn_with_log(
253
- "At least one file is not clean, Junifer will "
254
- "consider this dataset as dirty."
282
+ "At least one file is not clean, "
283
+ f"marking dataset (id: {self._dataset.id}) as dirty."
255
284
  )
256
285
  else:
257
- logger.debug("Dataset is clean")
286
+ logger.debug(f"Dataset (id: {self._dataset.id}) is clean")
258
287
 
259
288
  else:
260
289
  logger.debug(f"Installing dataset {self.uri} to {self._datadir}")
@@ -3,12 +3,14 @@
3
3
  # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
4
  # License: AGPL
5
5
 
6
+ import warnings
6
7
  from pathlib import Path
7
8
 
8
9
  import datalad.api as dl
9
10
  import pytest
10
11
 
11
12
  from junifer.datagrabber import DataladDataGrabber
13
+ from junifer.utils import config
12
14
 
13
15
 
14
16
  _testing_dataset = {
@@ -94,6 +96,12 @@ def test_DataladDataGrabber_install_errors(
94
96
  with pytest.raises(ValueError, match=r"different ID"):
95
97
  with dg:
96
98
  pass
99
+ # Set config to skip id check and test
100
+ config.set(key="datagrabber.skipidcheck", val=True)
101
+ with dg:
102
+ pass
103
+ # Reset config
104
+ config.delete("datagrabber.skipidcheck")
97
105
 
98
106
  elem1_t1w = datadir / "example_bids/sub-01/anat/sub-01_T1w.nii.gz"
99
107
  elem1_t1w.unlink()
@@ -104,6 +112,14 @@ def test_DataladDataGrabber_install_errors(
104
112
  with pytest.warns(RuntimeWarning, match=r"one file is not clean"):
105
113
  with dg:
106
114
  pass
115
+ # Set config to skip dirty check and test
116
+ with warnings.catch_warnings():
117
+ warnings.simplefilter("error")
118
+ config.set(key="datagrabber.skipdirtycheck", val=True)
119
+ with dg:
120
+ pass
121
+ # Reset config
122
+ config.delete("datagrabber.skipdirtycheck")
107
123
 
108
124
 
109
125
  def test_DataladDataGrabber_clone_cleanup(
@@ -246,7 +262,7 @@ def test_DataladDataGrabber_previously_cloned(
246
262
  meta = elem1["BOLD"]["meta"]
247
263
  assert "datagrabber" in meta
248
264
  assert "datalad_dirty" in meta["datagrabber"]
249
- assert meta["datagrabber"]["datalad_dirty"] is False
265
+ assert meta["datagrabber"]["datalad_dirty"] is True
250
266
  assert "datalad_commit_id" in meta["datagrabber"]
251
267
  assert meta["datagrabber"]["datalad_commit_id"] == commit
252
268
  assert "datalad_id" in meta["datagrabber"]
@@ -326,7 +342,7 @@ def test_DataladDataGrabber_previously_cloned_and_get(
326
342
  meta = elem1["BOLD"]["meta"]
327
343
  assert "datagrabber" in meta
328
344
  assert "datalad_dirty" in meta["datagrabber"]
329
- assert meta["datagrabber"]["datalad_dirty"] is False
345
+ assert meta["datagrabber"]["datalad_dirty"] is True
330
346
  assert "datalad_commit_id" in meta["datagrabber"]
331
347
  assert meta["datagrabber"]["datalad_commit_id"] == commit
332
348
  assert "datalad_id" in meta["datagrabber"]
@@ -30,6 +30,9 @@ class WorkDirManager(metaclass=Singleton):
30
30
  workdir : str or pathlib.Path, optional
31
31
  The path to the super-directory. If None, "TMPDIR/junifer" is used
32
32
  where TMPDIR is the platform-dependent temporary directory.
33
+ cleanup : bool, optional
34
+ If False, the directories are not cleaned up after the object is
35
+ destroyed. This is useful for debugging purposes (default True).
33
36
 
34
37
  Attributes
35
38
  ----------
@@ -39,14 +42,11 @@ class WorkDirManager(metaclass=Singleton):
39
42
  The path to the element directory.
40
43
  root_tempdir : pathlib.Path or None
41
44
  The path to the root temporary directory.
42
- cleanup : bool, optional
43
- If False, the directories are not cleaned up after the object is
44
- destroyed. This is useful for debugging purposes (default True).
45
45
 
46
46
  """
47
47
 
48
48
  def __init__(
49
- self, workdir: Optional[Union[str, Path]] = None, cleanup=True
49
+ self, workdir: Optional[Union[str, Path]] = None, cleanup: bool = True
50
50
  ) -> None:
51
51
  """Initialize the class."""
52
52
  self._workdir = Path(workdir) if isinstance(workdir, str) else workdir
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: junifer
3
- Version: 0.0.6.dev277
3
+ Version: 0.0.6.dev299
4
4
  Summary: JUelich NeuroImaging FEature extractoR
5
5
  Author-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
6
6
  Maintainer-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
@@ -1,13 +1,13 @@
1
1
  junifer/__init__.py,sha256=2McgH1yNue6Z1V26-uN_mfMjbTcx4CLhym-DMBl5xA4,266
2
2
  junifer/__init__.pyi,sha256=SsTvgq2Dod6UqJN96GH1lCphH6hJQQurEJHGNhHjGUI,508
3
- junifer/_version.py,sha256=oxdSo7e4dHuWGJ6fcFCd_o22QGOenmAuWxLqOvENYXw,428
3
+ junifer/_version.py,sha256=725_F3dOAgOL9Sw-MMC-B_RSYBVTStBAyk4cmIorMWI,428
4
4
  junifer/conftest.py,sha256=PWYkkRDU8ly2lYwv7VBKMHje4et6HX7Yey3Md_I2KbA,613
5
5
  junifer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  junifer/stats.py,sha256=e9aaagMGtgpRfW3Wdpz9ocpnYld1IWylCDcjFUgX9Mk,6225
7
7
  junifer/api/__init__.py,sha256=aAXW_KAEGQ8aAP5Eni2G1R4MWBF7UgjKOgM6akLuJco,252
8
8
  junifer/api/__init__.pyi,sha256=UJu55ApMFd43N0xlQyNKrYpCdzqhAxA3Jjaj0ETwCXU,169
9
9
  junifer/api/decorators.py,sha256=xphy55NJHnMZnJ-aNA70UzHUJ3SIgh5Xc8ekcozvj3U,2854
10
- junifer/api/functions.py,sha256=ebKz9WVdDcVWX32p2MHiYEEN-FEcsGcRWEN6u4pFnro,12826
10
+ junifer/api/functions.py,sha256=Tq1LKoxJuHHylcCFJ6SrPoPriIsnTLdbQ5K6w8gdTE8,13697
11
11
  junifer/api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  junifer/api/queue_context/__init__.py,sha256=glr8x4aMm4EvVrHywDIlugdNlwD1RzqV2FTDNPqYQZ4,204
13
13
  junifer/api/queue_context/__init__.pyi,sha256=LoDQFGZ9wCDmgx5a1_nhKo4zOSvqViXZ8V882DksF7U,246
@@ -40,11 +40,11 @@ junifer/api/res/fsl/flirt,sha256=tSjiUco8ui8AbHD7mTzChEwbR0Rf_4iJTgzYTPF_WuQ,42
40
40
  junifer/api/res/fsl/img2imgcoord,sha256=Zmaw3oJYrEltcXiPyEubXry9ppAq3SND52tdDWGgeZk,49
41
41
  junifer/api/res/fsl/run_fsl_docker.sh,sha256=pq-fcNdLuvHzVIQePN4GebZGlcE2UF-xj5rBIqAMz4g,1122
42
42
  junifer/api/res/fsl/std2imgcoord,sha256=-X5wRH6XMl0yqnTACJX6MFhO8DFOEWg42MHRxGvimXg,49
43
- junifer/api/tests/test_functions.py,sha256=aBAZ2EveiBHbAM5w6j2QxMHBze-XiVD3Td1kAE946ps,17786
43
+ junifer/api/tests/test_functions.py,sha256=PPkjs_FqjZZgsEa3a81ulzPxLskVh5HmnaG8TaNCwR0,18084
44
44
  junifer/cli/__init__.py,sha256=DS3kZKHeVDxt6d1MLBerZ2fcAwrEBHee5JOBhOLajUI,197
45
45
  junifer/cli/__init__.pyi,sha256=PiV4znUnzSeuSSJGz-RT8N21PiMqoSMwYcypi7nt2Js,40
46
- junifer/cli/cli.py,sha256=kzSM-5nZWgQ4iaGbcjDkU2JgdYcUF-zsYskuq9_ewM0,13195
47
- junifer/cli/parser.py,sha256=Ok_ADyoDfjlAxl9NP36dtzFHp9QTL87V_cRxCa44UKs,8336
46
+ junifer/cli/cli.py,sha256=Q0l7dBclLrM0P5MU2G0MA7W8u23VtqIQdwaeoOy-_ws,13519
47
+ junifer/cli/parser.py,sha256=ouVnk4NrOmVMNnQDMsqAjt2BaOT05bNJq0LVRsIakXI,8358
48
48
  junifer/cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  junifer/cli/utils.py,sha256=AbPQC0Kl-tHMNKiPxp_01gLAGD3IGoLbsq3rXyPMM-c,3116
50
50
  junifer/cli/tests/test_cli.py,sha256=AYL4my12GmFRCbI3JV7-rju32heYxAqbXNwnV8PwqVY,10982
@@ -123,7 +123,7 @@ junifer/data/tests/test_template_spaces.py,sha256=PJulN7xHpAcSOTY-UzTG_WPywZEBSl
123
123
  junifer/datagrabber/__init__.py,sha256=EHIK-lbjuvkt0V8ypFvLSt85OAAXSkaxBmVlCbNNz8M,323
124
124
  junifer/datagrabber/__init__.pyi,sha256=zOQE4TaCKXBTHnNqgmECtsszWIOHYiQ1CUEeXXFU9F4,832
125
125
  junifer/datagrabber/base.py,sha256=a3_fUZIN5Bqhq2f4ldpwk_eWeSVRDpDmx2QGIKzCtkg,6761
126
- junifer/datagrabber/datalad_base.py,sha256=2g-e_pLG0Legx4BvisrnGWYi1NCTyOkCi09QxbKX18M,11415
126
+ junifer/datagrabber/datalad_base.py,sha256=v_qGP66zk1-a-nU_u4qoSRNWYuh8YBdjhKkvzISgJWM,12586
127
127
  junifer/datagrabber/dmcc13_benchmark.py,sha256=VMyiwvkr4qSvzBICSksPPKOI2w_WVo06H89Url-hrNs,12819
128
128
  junifer/datagrabber/multiple.py,sha256=4tCOzojs3hoG7daHJJ7HUsx15atWR5nTmyP0S0__aig,6666
129
129
  junifer/datagrabber/pattern.py,sha256=UwJQ0MObBIS6eHH9FfoM_sBYuNM9n5NAX7DA0HdtL1A,18709
@@ -146,7 +146,7 @@ junifer/datagrabber/hcp1200/hcp1200.py,sha256=L_JTY0RYQ_Wst2La5EaGVDbya7IfSkTVkK
146
146
  junifer/datagrabber/hcp1200/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
147
  junifer/datagrabber/hcp1200/tests/test_hcp1200.py,sha256=HeXlD6wjvDq0EyqlB_nPqfXSIhAzALYAYjSCAjNOGGg,10972
148
148
  junifer/datagrabber/tests/test_base.py,sha256=fZdVhNhvfht9lpTHrAUf5E6mAfNNUP7OTQ5KLaBQ1gI,3506
149
- junifer/datagrabber/tests/test_datalad_base.py,sha256=5QSgsloHROVjp0g1UxXlk-Zmk-vHsLHGn05DJmmNkTI,16261
149
+ junifer/datagrabber/tests/test_datalad_base.py,sha256=nPF_N2Q09tgPmd5TD0dI9KU8G8HHLmydFa3agamijI8,16790
150
150
  junifer/datagrabber/tests/test_dmcc13_benchmark.py,sha256=QSdYAAwAj1DoE1oLhoraIc4lAgUgIaJyrtcOs_witzM,9914
151
151
  junifer/datagrabber/tests/test_multiple.py,sha256=tZBQhlEiSE1PeQ5E3TtuVgsHENquna9t39p54AJ-O5w,9963
152
152
  junifer/datagrabber/tests/test_pattern.py,sha256=H55jYRPfT3rMsoIQOAnWJgw3nGrkU7m2xFa3-ed6NQE,9527
@@ -268,7 +268,7 @@ junifer/pipeline/pipeline_step_mixin.py,sha256=oXfJh27yifHs1V3V_tMPCanRiHX1ggOVI
268
268
  junifer/pipeline/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
269
269
  junifer/pipeline/update_meta_mixin.py,sha256=yzGCx8AUbc9mMnWKRu4qaIXTBBSIxtNlGH5zIQIUvzM,1812
270
270
  junifer/pipeline/utils.py,sha256=27KYbUS6t1kb3vP_C5BoRBFfKPzfUKQK8Ut-aBERshk,10285
271
- junifer/pipeline/workdir_manager.py,sha256=T7-sZY_Gj0SM7p9N1ATjUFK2T-6CYIMQeYwHpBz96Gs,8616
271
+ junifer/pipeline/workdir_manager.py,sha256=r5hhizktLat2bN_A-ZGeeBVWmpRUkUCiZeIDxG-9umM,8624
272
272
  junifer/pipeline/tests/test_marker_collection.py,sha256=edBHfmwMTXG_q0ZagApbAbkFNoegi3hVEQiNcBtZOKc,6959
273
273
  junifer/pipeline/tests/test_pipeline_component_registry.py,sha256=mrbz285K_TzSILRn9X-AyzcNXuPRHGBZY6dQiq5_9So,5776
274
274
  junifer/pipeline/tests/test_pipeline_step_mixin.py,sha256=KCdhFdThm9TGkUvhGzQF3zR9SoZ9ont1z8yZELB2TtQ,7752
@@ -341,10 +341,10 @@ junifer/utils/tests/test_config.py,sha256=7ltIXuwb_W4Mv_1dxQWyiyM10XgUAfsWKV6D_i
341
341
  junifer/utils/tests/test_fs.py,sha256=WQS7cKlKEZ742CIuiOYYpueeAhY9PqlastfDVpVVtvE,923
342
342
  junifer/utils/tests/test_helpers.py,sha256=k5qqfxK8dFyuewTJyR1Qn6-nFaYNuVr0ysc18bfPjyU,929
343
343
  junifer/utils/tests/test_logging.py,sha256=duO4ou365hxwa_kwihFtKPLaL6LC5XHiyhOijrrngbA,8009
344
- junifer-0.0.6.dev277.dist-info/AUTHORS.rst,sha256=rmULKpchpSol4ExWFdm-qu4fkpSZPYqIESVJBZtGb6E,163
345
- junifer-0.0.6.dev277.dist-info/LICENSE.md,sha256=MqCnOBu8uXsEOzRZWh9EBVfVz-kE9NkXcLCrtGXo2yU,34354
346
- junifer-0.0.6.dev277.dist-info/METADATA,sha256=_f6DUBkVFhbhg_l8PQXSibG-3q9WIM6EP9PBvayajuA,8429
347
- junifer-0.0.6.dev277.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
348
- junifer-0.0.6.dev277.dist-info/entry_points.txt,sha256=6O8ru0BP-SP7YMUZiizFNoaZ2HvJpadO2G7nKk4PwjI,48
349
- junifer-0.0.6.dev277.dist-info/top_level.txt,sha256=4bAq1R2QFQ4b3hohjys2JBvxrl0GKk5LNFzYvz9VGcA,8
350
- junifer-0.0.6.dev277.dist-info/RECORD,,
344
+ junifer-0.0.6.dev299.dist-info/AUTHORS.rst,sha256=rmULKpchpSol4ExWFdm-qu4fkpSZPYqIESVJBZtGb6E,163
345
+ junifer-0.0.6.dev299.dist-info/LICENSE.md,sha256=MqCnOBu8uXsEOzRZWh9EBVfVz-kE9NkXcLCrtGXo2yU,34354
346
+ junifer-0.0.6.dev299.dist-info/METADATA,sha256=BJYB-ABLfZGsNi7s6U-r36VN0lNHYn83wbqsdQX-DbU,8429
347
+ junifer-0.0.6.dev299.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
348
+ junifer-0.0.6.dev299.dist-info/entry_points.txt,sha256=6O8ru0BP-SP7YMUZiizFNoaZ2HvJpadO2G7nKk4PwjI,48
349
+ junifer-0.0.6.dev299.dist-info/top_level.txt,sha256=4bAq1R2QFQ4b3hohjys2JBvxrl0GKk5LNFzYvz9VGcA,8
350
+ junifer-0.0.6.dev299.dist-info/RECORD,,