junifer 0.0.7.dev332__py3-none-any.whl → 0.0.8__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 +9 -19
- junifer/api/__init__.pyi +17 -2
- junifer/api/functions.py +222 -39
- junifer/api/queue_context/__init__.pyi +11 -3
- junifer/api/queue_context/gnu_parallel_local_adapter.py +81 -120
- junifer/api/queue_context/htcondor_adapter.py +118 -181
- junifer/api/queue_context/queue_context_adapter.py +51 -7
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +10 -35
- junifer/api/queue_context/tests/test_htcondor_adapter.py +13 -50
- junifer/api/res/fsl/run_fsl_docker.sh +4 -0
- junifer/api/tests/test_functions.py +863 -36
- junifer/cli/__init__.py +1 -7
- junifer/cli/cli.py +41 -22
- junifer/cli/parser.py +23 -147
- junifer/cli/tests/data/gmd_mean.yaml +6 -6
- junifer/cli/tests/data/gmd_mean_htcondor.yaml +6 -5
- junifer/cli/tests/data/partly_cloudy_agg_mean_tian.yml +1 -0
- junifer/cli/tests/test_cli.py +120 -4
- junifer/cli/tests/test_cli_utils.py +23 -6
- junifer/cli/utils.py +14 -9
- junifer/configs/__init__.py +5 -0
- junifer/configs/__init__.pyi +0 -0
- junifer/configs/juseless/datagrabbers/__init__.pyi +4 -2
- junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +18 -24
- junifer/configs/juseless/datagrabbers/camcan_vbm.py +20 -27
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +44 -52
- junifer/configs/juseless/datagrabbers/tests/test_ixi_vbm.py +0 -7
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -19
- junifer/configs/juseless/datagrabbers/ucla.py +111 -104
- junifer/configs/juseless/datagrabbers/ukb_vbm.py +19 -25
- junifer/configs/py.typed +0 -0
- junifer/conftest.py +63 -24
- junifer/data/_dispatch.py +9 -19
- junifer/data/coordinates/_ants_coordinates_warper.py +4 -1
- junifer/data/coordinates/_coordinates.py +51 -6
- junifer/data/coordinates/_fsl_coordinates_warper.py +4 -1
- junifer/data/coordinates/tests/test_coordinates.py +15 -3
- junifer/data/coordinates/tests/test_coordinates_names.py +37 -0
- junifer/data/maps/_ants_maps_warper.py +18 -12
- junifer/data/maps/_fsl_maps_warper.py +7 -3
- junifer/data/maps/_maps.py +12 -8
- junifer/data/maps/tests/test_maps.py +13 -21
- junifer/data/masks/_ants_mask_warper.py +18 -12
- junifer/data/masks/_fsl_mask_warper.py +7 -3
- junifer/data/masks/_masks.py +15 -12
- junifer/data/masks/tests/test_masks.py +20 -17
- junifer/data/parcellations/_ants_parcellation_warper.py +18 -12
- junifer/data/parcellations/_fsl_parcellation_warper.py +7 -5
- junifer/data/parcellations/_parcellations.py +125 -91
- junifer/data/parcellations/tests/test_parcellations.py +122 -1
- junifer/data/template_spaces.py +117 -50
- junifer/data/tests/test_template_spaces.py +10 -7
- junifer/data/utils.py +10 -8
- junifer/datagrabber/__init__.pyi +38 -5
- junifer/datagrabber/aomic/__init__.pyi +8 -1
- junifer/datagrabber/aomic/_types.py +22 -0
- junifer/datagrabber/aomic/id1000.py +193 -183
- junifer/datagrabber/aomic/piop1.py +215 -259
- junifer/datagrabber/aomic/piop2.py +211 -244
- junifer/datagrabber/aomic/tests/test_id1000.py +70 -53
- junifer/datagrabber/aomic/tests/test_piop1.py +98 -102
- junifer/datagrabber/aomic/tests/test_piop2.py +88 -85
- junifer/datagrabber/base.py +253 -79
- junifer/datagrabber/datalad_base.py +127 -76
- junifer/datagrabber/dmcc13_benchmark.py +204 -289
- junifer/datagrabber/hcp1200/__init__.pyi +7 -2
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +61 -40
- junifer/datagrabber/hcp1200/hcp1200.py +151 -164
- junifer/datagrabber/hcp1200/tests/test_hcp1200.py +116 -128
- junifer/datagrabber/multiple.py +183 -63
- junifer/datagrabber/pattern.py +358 -227
- junifer/datagrabber/pattern_datalad.py +84 -124
- junifer/datagrabber/pattern_validation_mixin.py +22 -50
- junifer/datagrabber/tests/test_base.py +17 -4
- junifer/datagrabber/tests/test_datalad_base.py +20 -27
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +110 -122
- junifer/datagrabber/tests/test_multiple.py +293 -31
- junifer/datagrabber/tests/test_pattern.py +577 -18
- junifer/datagrabber/tests/test_pattern_datalad.py +177 -107
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +9 -51
- junifer/datareader/default.py +8 -5
- junifer/datareader/tests/test_default_reader.py +1 -1
- junifer/external/BrainPrint/.codecov.yml +2 -0
- junifer/external/BrainPrint/.codespellignore +2 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/bug-report.md +45 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/documentation.md +12 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/feature-request.md +24 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/questions-help-support.md +28 -0
- junifer/external/BrainPrint/.github/dependabot.yml +6 -0
- junifer/external/BrainPrint/.github/workflows/build.yml +53 -0
- junifer/external/BrainPrint/.github/workflows/code-style.yml +44 -0
- junifer/external/BrainPrint/.github/workflows/doc.yml +65 -0
- junifer/external/BrainPrint/.github/workflows/publish.yml +31 -0
- junifer/external/BrainPrint/.github/workflows/pytest.yml +54 -0
- junifer/external/BrainPrint/.gitignore +123 -0
- junifer/external/BrainPrint/LICENSE +21 -0
- junifer/external/BrainPrint/README.md +108 -0
- junifer/external/BrainPrint/brainprint/cli/__init__.py +11 -0
- junifer/external/BrainPrint/brainprint/cli/help_text.py +169 -0
- junifer/external/BrainPrint/brainprint/cli/parser.py +150 -0
- junifer/external/BrainPrint/brainprint/cli/utils.py +14 -0
- junifer/external/BrainPrint/brainprint/commands/__init__.py +0 -0
- junifer/external/BrainPrint/brainprint/commands/sys_info.py +18 -0
- junifer/external/BrainPrint/brainprint/utils/tests/__init__.py +0 -0
- junifer/external/BrainPrint/brainprint/utils/tests/test_config.py +33 -0
- junifer/external/BrainPrint/doc/Makefile +20 -0
- junifer/external/BrainPrint/doc/_static/.gitkeep +0 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/class.rst +10 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/function.rst +8 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/module.rst +6 -0
- junifer/external/BrainPrint/doc/api/index.rst +11 -0
- junifer/external/BrainPrint/doc/conf.py +272 -0
- junifer/external/BrainPrint/doc/index.rst +140 -0
- junifer/external/BrainPrint/doc/links.inc +36 -0
- junifer/external/BrainPrint/doc/make.bat +35 -0
- junifer/external/BrainPrint/doc/references.bib +23 -0
- junifer/external/BrainPrint/pyproject.toml +170 -0
- junifer/external/BrainPrint/setup.py +3 -0
- junifer/external/__init__.py +5 -0
- junifer/external/__init__.pyi +0 -0
- junifer/external/nilearn/junifer_connectivity_measure.py +95 -39
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +226 -67
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +39 -27
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +231 -21
- junifer/external/py.typed +0 -0
- junifer/markers/__init__.pyi +6 -3
- junifer/markers/base.py +126 -76
- junifer/markers/brainprint.py +30 -39
- junifer/markers/complexity/__init__.py +20 -3
- junifer/markers/complexity/complexity_base.py +40 -41
- junifer/markers/complexity/hurst_exponent.py +22 -35
- junifer/markers/complexity/multiscale_entropy_auc.py +53 -41
- junifer/markers/complexity/perm_entropy.py +22 -36
- junifer/markers/complexity/range_entropy.py +22 -35
- junifer/markers/complexity/range_entropy_auc.py +27 -36
- junifer/markers/complexity/sample_entropy.py +22 -36
- junifer/markers/complexity/tests/test_complexity_registry.py +48 -0
- junifer/markers/complexity/tests/test_hurst_exponent.py +47 -36
- junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +50 -36
- junifer/markers/complexity/tests/test_perm_entropy.py +48 -36
- junifer/markers/complexity/tests/test_range_entropy.py +47 -36
- junifer/markers/complexity/tests/test_range_entropy_auc.py +47 -36
- junifer/markers/complexity/tests/test_sample_entropy.py +48 -36
- junifer/markers/complexity/tests/test_weighted_perm_entropy.py +50 -36
- junifer/markers/complexity/weighted_perm_entropy.py +22 -36
- junifer/markers/ets_rss.py +35 -31
- junifer/markers/falff/__init__.pyi +7 -1
- junifer/markers/falff/_afni_falff.py +22 -9
- junifer/markers/falff/_junifer_falff.py +47 -31
- junifer/markers/falff/falff_base.py +80 -60
- junifer/markers/falff/falff_maps.py +17 -41
- junifer/markers/falff/falff_parcels.py +26 -51
- junifer/markers/falff/falff_spheres.py +34 -61
- junifer/markers/falff/tests/test_falff_maps.py +20 -23
- junifer/markers/falff/tests/test_falff_mask.py +99 -0
- junifer/markers/falff/tests/test_falff_parcels.py +14 -10
- junifer/markers/falff/tests/test_falff_spheres.py +14 -10
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +32 -34
- junifer/markers/functional_connectivity/edge_functional_connectivity_maps.py +12 -25
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +19 -34
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +24 -44
- junifer/markers/functional_connectivity/functional_connectivity_base.py +50 -40
- junifer/markers/functional_connectivity/functional_connectivity_maps.py +12 -25
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +19 -34
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +24 -45
- junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +21 -22
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_maps.py +8 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +8 -4
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +8 -4
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_maps.py +8 -7
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +9 -5
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +8 -12
- junifer/markers/maps_aggregation.py +77 -55
- junifer/markers/parcel_aggregation.py +91 -70
- junifer/markers/reho/__init__.pyi +7 -1
- junifer/markers/reho/_afni_reho.py +23 -14
- junifer/markers/reho/_junifer_reho.py +112 -123
- junifer/markers/reho/reho_base.py +115 -37
- junifer/markers/reho/reho_maps.py +18 -32
- junifer/markers/reho/reho_parcels.py +26 -41
- junifer/markers/reho/reho_spheres.py +33 -54
- junifer/markers/reho/tests/test_junifer_reho.py +178 -0
- junifer/markers/reho/tests/test_reho_maps.py +27 -25
- junifer/markers/reho/tests/test_reho_parcels.py +28 -22
- junifer/markers/reho/tests/test_reho_spheres.py +16 -12
- junifer/markers/sphere_aggregation.py +88 -72
- junifer/markers/temporal_snr/temporal_snr_base.py +32 -30
- junifer/markers/temporal_snr/temporal_snr_maps.py +9 -18
- junifer/markers/temporal_snr/temporal_snr_parcels.py +19 -27
- junifer/markers/temporal_snr/temporal_snr_spheres.py +27 -41
- junifer/markers/temporal_snr/tests/test_temporal_snr_base.py +2 -2
- junifer/markers/temporal_snr/tests/test_temporal_snr_maps.py +17 -22
- junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +11 -3
- junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +9 -9
- junifer/markers/tests/test_brainprint.py +10 -9
- junifer/markers/tests/test_ets_rss.py +7 -3
- junifer/markers/tests/test_lost_regions.py +279 -0
- junifer/markers/tests/test_maps_aggregation.py +67 -114
- junifer/markers/tests/test_marker_utils.py +40 -1
- junifer/markers/tests/test_markers_base.py +275 -6
- junifer/markers/tests/test_parcel_aggregation.py +91 -53
- junifer/markers/tests/test_sphere_aggregation.py +53 -47
- junifer/markers/utils.py +267 -5
- junifer/onthefly/__init__.py +2 -3
- junifer/onthefly/__init__.pyi +4 -0
- junifer/onthefly/_brainprint.py +3 -5
- junifer/onthefly/py.typed +0 -0
- junifer/onthefly/read_transform.py +11 -9
- junifer/onthefly/tests/test_read_transform.py +7 -7
- junifer/pipeline/__init__.pyi +4 -2
- junifer/pipeline/marker_collection.py +14 -10
- junifer/pipeline/pipeline_component_registry.py +25 -6
- junifer/pipeline/pipeline_step_mixin.py +5 -12
- junifer/pipeline/tests/test_data_object_dumper.py +10 -10
- junifer/pipeline/tests/test_marker_collection.py +145 -168
- junifer/pipeline/tests/test_pipeline_component_registry.py +52 -8
- junifer/pipeline/tests/test_pipeline_step_mixin.py +12 -26
- junifer/pipeline/tests/test_update_meta_mixin.py +4 -5
- junifer/pipeline/tests/test_workdir_manager.py +39 -0
- junifer/pipeline/update_meta_mixin.py +13 -10
- junifer/pipeline/utils.py +22 -17
- junifer/pipeline/workdir_manager.py +41 -32
- junifer/preprocess/__init__.pyi +9 -4
- junifer/preprocess/_temporal_filter.py +34 -33
- junifer/preprocess/_temporal_slicer.py +17 -30
- junifer/preprocess/base.py +99 -55
- junifer/preprocess/confounds/__init__.pyi +10 -2
- junifer/preprocess/confounds/fmriprep_confound_remover.py +87 -109
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +64 -45
- junifer/preprocess/smoothing/__init__.pyi +2 -2
- junifer/preprocess/smoothing/_afni_smoothing.py +8 -7
- junifer/preprocess/smoothing/_fsl_smoothing.py +6 -4
- junifer/preprocess/smoothing/_nilearn_smoothing.py +7 -5
- junifer/preprocess/smoothing/smoothing.py +59 -40
- junifer/preprocess/smoothing/tests/test_smoothing.py +28 -8
- junifer/preprocess/tests/test_preprocess_base.py +17 -9
- junifer/preprocess/tests/test_temporal_filter.py +37 -16
- junifer/preprocess/tests/test_temporal_slicer.py +12 -12
- junifer/preprocess/warping/__init__.pyi +2 -2
- junifer/preprocess/warping/_ants_warper.py +56 -40
- junifer/preprocess/warping/_fsl_warper.py +49 -36
- junifer/preprocess/warping/_utils.py +106 -0
- junifer/preprocess/warping/space_warper.py +99 -98
- junifer/preprocess/warping/tests/test_space_warper.py +46 -41
- junifer/preprocess/warping/tests/test_warping_utils.py +163 -0
- junifer/stats.py +46 -34
- junifer/storage/__init__.pyi +8 -4
- junifer/storage/base.py +129 -64
- junifer/storage/hdf5.py +307 -199
- junifer/storage/pandas_base.py +46 -24
- junifer/storage/sqlite.py +99 -62
- junifer/storage/tests/data/collected_h5io_fork.hdf5 +0 -0
- junifer/storage/tests/test_hdf5.py +147 -12
- junifer/storage/tests/test_repeated_storage.py +293 -0
- junifer/storage/tests/test_sqlite.py +9 -20
- junifer/storage/tests/test_storage_base.py +18 -21
- junifer/storage/tests/test_utils.py +83 -22
- junifer/storage/utils.py +58 -38
- junifer/testing/__init__.pyi +2 -2
- junifer/testing/datagrabbers.py +480 -44
- junifer/testing/registry.py +12 -0
- junifer/testing/tests/test_adhdtesting_datagrabber.py +24 -0
- junifer/testing/tests/test_oasisvmbtesting_datagrabber.py +5 -0
- junifer/testing/tests/test_partlycloudytesting_datagrabber.py +52 -0
- junifer/testing/tests/test_spmauditory_datagrabber.py +16 -0
- junifer/testing/tests/test_testing_registry.py +31 -0
- junifer/testing/tests/test_testing_utils.py +35 -0
- junifer/testing/tests/test_uclacnpvbmtesting_datagrabber.py +81 -0
- junifer/testing/utils.py +33 -1
- junifer/tests/test_stats.py +1 -5
- junifer/typing/__init__.pyi +2 -0
- junifer/typing/_typing.py +34 -19
- junifer/typing/py.typed +0 -0
- junifer/utils/__init__.pyi +10 -1
- junifer/utils/_config.py +1 -2
- junifer/utils/helpers.py +68 -2
- junifer/utils/logging.py +31 -7
- junifer/utils/tests/test_helpers.py +36 -1
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/METADATA +43 -35
- junifer-0.0.8.dist-info/RECORD +402 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/WHEEL +1 -1
- junifer/cli/tests/test_parser.py +0 -280
- junifer/external/h5io/h5io/__init__.py +0 -15
- junifer/external/h5io/h5io/_h5io.py +0 -767
- junifer/external/h5io/h5io/_version.py +0 -1
- junifer/external/h5io/h5io/chunked_array.py +0 -94
- junifer/external/h5io/h5io/chunked_list.py +0 -65
- junifer/markers/complexity/__init__.pyi +0 -17
- junifer-0.0.7.dev332.dist-info/RECORD +0 -353
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/AUTHORS.rst +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/LICENSE.md +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/top_level.txt +0 -0
junifer/cli/__init__.py
CHANGED
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
from importlib.metadata import entry_points
|
|
7
7
|
|
|
8
8
|
import lazy_loader as lazy
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
if sys.version_info < (3, 11): # pragma: no cover
|
|
12
|
-
from importlib_metadata import entry_points
|
|
13
|
-
else:
|
|
14
|
-
from importlib.metadata import entry_points
|
|
15
|
-
|
|
16
|
-
|
|
17
11
|
__getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
|
|
18
12
|
|
|
19
13
|
|
junifer/cli/cli.py
CHANGED
|
@@ -8,7 +8,6 @@ import pathlib
|
|
|
8
8
|
import subprocess
|
|
9
9
|
import sys
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Optional, Union
|
|
12
11
|
|
|
13
12
|
import click
|
|
14
13
|
|
|
@@ -18,7 +17,7 @@ from ..utils import (
|
|
|
18
17
|
raise_error,
|
|
19
18
|
yaml,
|
|
20
19
|
)
|
|
21
|
-
from .parser import parse_elements
|
|
20
|
+
from .parser import parse_elements
|
|
22
21
|
from .utils import (
|
|
23
22
|
_get_dependency_information,
|
|
24
23
|
_get_environment_information,
|
|
@@ -45,8 +44,30 @@ __all__ = [
|
|
|
45
44
|
]
|
|
46
45
|
|
|
47
46
|
|
|
47
|
+
def _parse_yaml(filepath: click.Path) -> dict:
|
|
48
|
+
"""Parse the YAML file and set up the working directory.
|
|
49
|
+
|
|
50
|
+
The working directory is set up before anything else, as all the
|
|
51
|
+
components assume it is available.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
filepath : click.Path
|
|
56
|
+
The filepath to the configuration file.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
dict
|
|
61
|
+
The configuration.
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
config = cli_func.parse_yaml(filepath) # type: ignore
|
|
65
|
+
cli_func._setup_workdir(config.get("workdir"))
|
|
66
|
+
return config
|
|
67
|
+
|
|
68
|
+
|
|
48
69
|
def _validate_optional_verbose(
|
|
49
|
-
ctx: click.Context, param: str, value:
|
|
70
|
+
ctx: click.Context, param: str, value: str | None
|
|
50
71
|
):
|
|
51
72
|
"""Validate optional verbose option.
|
|
52
73
|
|
|
@@ -71,9 +92,7 @@ def _validate_optional_verbose(
|
|
|
71
92
|
return _validate_verbose(ctx, param, value)
|
|
72
93
|
|
|
73
94
|
|
|
74
|
-
def _validate_verbose(
|
|
75
|
-
ctx: click.Context, param: str, value: str
|
|
76
|
-
) -> Union[str, int]:
|
|
95
|
+
def _validate_verbose(ctx: click.Context, param: str, value: str) -> str | int:
|
|
77
96
|
"""Validate verbose option.
|
|
78
97
|
|
|
79
98
|
Parameters
|
|
@@ -142,8 +161,8 @@ def cli() -> None: # pragma: no cover
|
|
|
142
161
|
def run(
|
|
143
162
|
filepath: click.Path,
|
|
144
163
|
element: tuple[str],
|
|
145
|
-
verbose:
|
|
146
|
-
verbose_datalad:
|
|
164
|
+
verbose: str | int,
|
|
165
|
+
verbose_datalad: str | int | None,
|
|
147
166
|
) -> None:
|
|
148
167
|
"""Run feature extraction.
|
|
149
168
|
|
|
@@ -165,7 +184,7 @@ def run(
|
|
|
165
184
|
configure_logging(level=verbose, level_datalad=verbose_datalad)
|
|
166
185
|
# TODO(synchon): add validation
|
|
167
186
|
# Parse YAML
|
|
168
|
-
config =
|
|
187
|
+
config = _parse_yaml(filepath)
|
|
169
188
|
# Retrieve working directory
|
|
170
189
|
workdir = config["workdir"]
|
|
171
190
|
# Fetch datagrabber
|
|
@@ -214,8 +233,8 @@ def run(
|
|
|
214
233
|
)
|
|
215
234
|
def collect(
|
|
216
235
|
filepath: click.Path,
|
|
217
|
-
verbose:
|
|
218
|
-
verbose_datalad:
|
|
236
|
+
verbose: str | int,
|
|
237
|
+
verbose_datalad: str | int | None,
|
|
219
238
|
) -> None:
|
|
220
239
|
"""Collect extracted features.
|
|
221
240
|
|
|
@@ -235,7 +254,7 @@ def collect(
|
|
|
235
254
|
configure_logging(level=verbose, level_datalad=verbose_datalad)
|
|
236
255
|
# TODO: add validation
|
|
237
256
|
# Parse YAML
|
|
238
|
-
config =
|
|
257
|
+
config = _parse_yaml(filepath)
|
|
239
258
|
# Fetch storage
|
|
240
259
|
storage = config["storage"]
|
|
241
260
|
# Perform operation
|
|
@@ -270,8 +289,8 @@ def queue(
|
|
|
270
289
|
element: tuple[str],
|
|
271
290
|
overwrite: bool,
|
|
272
291
|
submit: bool,
|
|
273
|
-
verbose:
|
|
274
|
-
verbose_datalad:
|
|
292
|
+
verbose: str | int,
|
|
293
|
+
verbose_datalad: str | int | None,
|
|
275
294
|
) -> None:
|
|
276
295
|
"""Queue feature extraction.
|
|
277
296
|
|
|
@@ -302,7 +321,7 @@ def queue(
|
|
|
302
321
|
configure_logging(level=verbose, level_datalad=verbose_datalad)
|
|
303
322
|
# TODO: add validation
|
|
304
323
|
# Parse YAML
|
|
305
|
-
config =
|
|
324
|
+
config = _parse_yaml(filepath)
|
|
306
325
|
# Check queue section
|
|
307
326
|
if "queue" not in config:
|
|
308
327
|
raise_error(f"No queue configuration found in {filepath}.")
|
|
@@ -433,8 +452,8 @@ def selftest(subpkg: str) -> None:
|
|
|
433
452
|
)
|
|
434
453
|
def reset(
|
|
435
454
|
filepath: click.Path,
|
|
436
|
-
verbose:
|
|
437
|
-
verbose_datalad:
|
|
455
|
+
verbose: str | int,
|
|
456
|
+
verbose_datalad: str | int | None,
|
|
438
457
|
) -> None:
|
|
439
458
|
"""Reset generated assets.
|
|
440
459
|
|
|
@@ -453,7 +472,7 @@ def reset(
|
|
|
453
472
|
# Setup logging
|
|
454
473
|
configure_logging(level=verbose, level_datalad=verbose_datalad)
|
|
455
474
|
# Parse YAML
|
|
456
|
-
config =
|
|
475
|
+
config = _parse_yaml(filepath)
|
|
457
476
|
# Perform operation
|
|
458
477
|
cli_func.reset(config)
|
|
459
478
|
|
|
@@ -487,9 +506,9 @@ def reset(
|
|
|
487
506
|
def list_elements(
|
|
488
507
|
filepath: click.Path,
|
|
489
508
|
element: tuple[str],
|
|
490
|
-
output_file:
|
|
491
|
-
verbose:
|
|
492
|
-
verbose_datalad:
|
|
509
|
+
output_file: click.Path | None,
|
|
510
|
+
verbose: str | int,
|
|
511
|
+
verbose_datalad: str | int | None,
|
|
493
512
|
) -> None:
|
|
494
513
|
"""List elements of a dataset.
|
|
495
514
|
|
|
@@ -513,7 +532,7 @@ def list_elements(
|
|
|
513
532
|
# Setup logging
|
|
514
533
|
configure_logging(level=verbose, level_datalad=verbose_datalad)
|
|
515
534
|
# Parse YAML
|
|
516
|
-
config =
|
|
535
|
+
config = _parse_yaml(filepath)
|
|
517
536
|
# Fetch datagrabber
|
|
518
537
|
datagrabber = config["datagrabber"]
|
|
519
538
|
# Parse elements
|
junifer/cli/parser.py
CHANGED
|
@@ -4,147 +4,19 @@
|
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
5
5
|
# License: AGPL
|
|
6
6
|
|
|
7
|
-
import importlib
|
|
8
|
-
import importlib.util
|
|
9
|
-
import sys
|
|
10
7
|
from pathlib import Path
|
|
11
|
-
from typing import Union
|
|
12
8
|
|
|
13
9
|
import pandas as pd
|
|
14
10
|
|
|
15
11
|
from ..typing import Elements
|
|
16
|
-
from ..utils import logger, raise_error, warn_with_log
|
|
12
|
+
from ..utils import logger, raise_error, warn_with_log
|
|
17
13
|
|
|
18
14
|
|
|
19
|
-
__all__ = ["parse_elements"
|
|
15
|
+
__all__ = ["parse_elements"]
|
|
20
16
|
|
|
21
17
|
|
|
22
|
-
def
|
|
23
|
-
"""Parse
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
filepath : str or pathlib.Path
|
|
28
|
-
The filepath to read from.
|
|
29
|
-
|
|
30
|
-
Returns
|
|
31
|
-
-------
|
|
32
|
-
dict
|
|
33
|
-
The contents represented as dictionary.
|
|
34
|
-
|
|
35
|
-
"""
|
|
36
|
-
# Convert str to Path
|
|
37
|
-
if not isinstance(filepath, Path):
|
|
38
|
-
filepath = Path(filepath)
|
|
39
|
-
|
|
40
|
-
logger.info(f"Parsing yaml file: {filepath.absolute()!s}")
|
|
41
|
-
# Filepath existence check
|
|
42
|
-
if not filepath.exists():
|
|
43
|
-
raise_error(f"File does not exist: {filepath.absolute()!s}")
|
|
44
|
-
# Filepath reading
|
|
45
|
-
contents = yaml.load(filepath)
|
|
46
|
-
if "elements" in contents:
|
|
47
|
-
if contents["elements"] is None:
|
|
48
|
-
raise_error(
|
|
49
|
-
"The elements key was defined but its content is empty. "
|
|
50
|
-
"Please define the elements to operate on or remove the key."
|
|
51
|
-
)
|
|
52
|
-
# load modules
|
|
53
|
-
if "with" in contents:
|
|
54
|
-
to_load = contents["with"]
|
|
55
|
-
# Convert load modules to list
|
|
56
|
-
if not isinstance(to_load, list):
|
|
57
|
-
to_load = [to_load]
|
|
58
|
-
# Initialize list to have absolute paths for custom modules
|
|
59
|
-
final_to_load = []
|
|
60
|
-
for t_module in to_load:
|
|
61
|
-
if t_module.endswith(".py"):
|
|
62
|
-
logger.debug(f"Importing file: {t_module}")
|
|
63
|
-
# This resolves both absolute and relative paths
|
|
64
|
-
file_path = filepath.parent / t_module
|
|
65
|
-
if not file_path.exists():
|
|
66
|
-
raise_error(
|
|
67
|
-
f"File in 'with' section does not exist: {file_path}"
|
|
68
|
-
)
|
|
69
|
-
# Add the parent directory to the sys.path so that the
|
|
70
|
-
# any imports from this module work correctly
|
|
71
|
-
t_path = str(file_path.parent)
|
|
72
|
-
if t_path not in sys.path:
|
|
73
|
-
sys.path.append(str(file_path.parent))
|
|
74
|
-
|
|
75
|
-
spec = importlib.util.spec_from_file_location(
|
|
76
|
-
t_module, file_path
|
|
77
|
-
)
|
|
78
|
-
module = importlib.util.module_from_spec(spec) # type: ignore
|
|
79
|
-
sys.modules[t_module] = module
|
|
80
|
-
spec.loader.exec_module(module) # type: ignore
|
|
81
|
-
|
|
82
|
-
# Add absolute path to final list
|
|
83
|
-
final_to_load.append(str(file_path.resolve()))
|
|
84
|
-
|
|
85
|
-
# Check if the module has junifer_module_deps function
|
|
86
|
-
if hasattr(module, "junifer_module_deps"):
|
|
87
|
-
logger.debug(
|
|
88
|
-
f"Module {t_module} has junifer_module_deps function"
|
|
89
|
-
)
|
|
90
|
-
# Get the dependencies
|
|
91
|
-
deps = module.junifer_module_deps()
|
|
92
|
-
# Add the dependencies to the final list
|
|
93
|
-
for dep in deps:
|
|
94
|
-
if dep not in final_to_load:
|
|
95
|
-
final_to_load.append(
|
|
96
|
-
str((file_path.parent / dep).resolve())
|
|
97
|
-
)
|
|
98
|
-
else:
|
|
99
|
-
logger.info(f"Importing module: {t_module}")
|
|
100
|
-
importlib.import_module(t_module)
|
|
101
|
-
# Add module to final list
|
|
102
|
-
final_to_load.append(t_module)
|
|
103
|
-
|
|
104
|
-
# Replace modules to be loaded so that custom modules will take the
|
|
105
|
-
# absolute path. This was not the case as found in #224. Similar thing
|
|
106
|
-
# is done with the storage URI below.
|
|
107
|
-
contents["with"] = final_to_load
|
|
108
|
-
|
|
109
|
-
# Compute path for the URI parameter in storage files that are relative
|
|
110
|
-
# This is a tricky thing that appeared in #127. The problem is that
|
|
111
|
-
# the path in the URI parameter is relative to YAML file, not to the
|
|
112
|
-
# current working directory. If we leave it as is in the contents
|
|
113
|
-
# dict, then it will be used later in the ``build`` function as is,
|
|
114
|
-
# which will be computed relative to the current working directory.
|
|
115
|
-
# The solution is to compute the absolute path and replace the
|
|
116
|
-
# relative path in the contents dict with the absolute path.
|
|
117
|
-
|
|
118
|
-
# Check if the storage file is defined
|
|
119
|
-
if "storage" in contents:
|
|
120
|
-
if "uri" in contents["storage"]:
|
|
121
|
-
# Check if the storage file is relative
|
|
122
|
-
uri_path = Path(contents["storage"]["uri"])
|
|
123
|
-
if not uri_path.is_absolute():
|
|
124
|
-
# Compute the absolute path
|
|
125
|
-
contents["storage"]["uri"] = str(
|
|
126
|
-
(filepath.parent / uri_path).resolve()
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
# Allow relative path if queue env kind is venv; same motivation as above
|
|
130
|
-
if "queue" in contents:
|
|
131
|
-
if "env" in contents["queue"]:
|
|
132
|
-
if "venv" == contents["queue"]["env"]["kind"]:
|
|
133
|
-
# Check if the env name is relative
|
|
134
|
-
venv_path = Path(contents["queue"]["env"]["name"])
|
|
135
|
-
if not venv_path.is_absolute():
|
|
136
|
-
# Compute the absolute path
|
|
137
|
-
contents["queue"]["env"]["name"] = str(
|
|
138
|
-
(filepath.parent / venv_path).resolve()
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
return contents
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def parse_elements(
|
|
145
|
-
element: tuple[str, ...], config: dict
|
|
146
|
-
) -> Union[Elements, None]:
|
|
147
|
-
"""Parse elements from cli.
|
|
18
|
+
def parse_elements(element: tuple[str, ...], config: dict) -> Elements | None:
|
|
19
|
+
"""Parse elements from cli, or from the configuration if not in the cli.
|
|
148
20
|
|
|
149
21
|
Parameters
|
|
150
22
|
----------
|
|
@@ -156,13 +28,13 @@ def parse_elements(
|
|
|
156
28
|
Returns
|
|
157
29
|
-------
|
|
158
30
|
list or None
|
|
159
|
-
The element(s) as list or None
|
|
31
|
+
The element(s) as list, or None (all the elements) if they are not in
|
|
32
|
+
the command-line options nor in the configuration.
|
|
160
33
|
|
|
161
34
|
Raises
|
|
162
35
|
------
|
|
163
36
|
ValueError
|
|
164
|
-
If
|
|
165
|
-
the configuration file.
|
|
37
|
+
If the ``elements`` key of the configuration has no value.
|
|
166
38
|
|
|
167
39
|
Warns
|
|
168
40
|
-----
|
|
@@ -172,9 +44,22 @@ def parse_elements(
|
|
|
172
44
|
|
|
173
45
|
"""
|
|
174
46
|
logger.debug(f"Parsing elements: {element}")
|
|
175
|
-
#
|
|
47
|
+
# Use the elements of the configuration if not in the command line
|
|
176
48
|
if not element:
|
|
177
|
-
|
|
49
|
+
if "elements" not in config:
|
|
50
|
+
# None to continue with all elements
|
|
51
|
+
return None
|
|
52
|
+
elements = config["elements"]
|
|
53
|
+
if elements is None:
|
|
54
|
+
raise_error(
|
|
55
|
+
"The `elements` key is set in the configuration, but its value"
|
|
56
|
+
" is `None`. It is likely that there is an empty `elements` "
|
|
57
|
+
"section in the yaml configuration file."
|
|
58
|
+
)
|
|
59
|
+
# A single element, and the elements with multiple values as tuples
|
|
60
|
+
if not isinstance(elements, list):
|
|
61
|
+
elements = [elements]
|
|
62
|
+
return [tuple(x) if isinstance(x, list) else x for x in elements]
|
|
178
63
|
# Check if the element is a file for single element;
|
|
179
64
|
# if yes, then parse elements from it
|
|
180
65
|
if len(element) == 1 and Path(element[0]).resolve().is_file():
|
|
@@ -183,7 +68,7 @@ def parse_elements(
|
|
|
183
68
|
# Process multi-keyed elements
|
|
184
69
|
elements = [tuple(x.split(",")) if "," in x else x for x in element]
|
|
185
70
|
logger.debug(f"Parsed elements: {elements}")
|
|
186
|
-
if
|
|
71
|
+
if "elements" in config:
|
|
187
72
|
warn_with_log(
|
|
188
73
|
"One or more elements have been specified in both the command "
|
|
189
74
|
"line and in the config file. The command line has precedence "
|
|
@@ -192,15 +77,6 @@ def parse_elements(
|
|
|
192
77
|
"the configuration file will be ignored. To remove this warning, "
|
|
193
78
|
"please remove the `elements` item from the configuration file."
|
|
194
79
|
)
|
|
195
|
-
elif elements is None:
|
|
196
|
-
# Check in config
|
|
197
|
-
elements = config.get("elements", None)
|
|
198
|
-
if elements is None:
|
|
199
|
-
raise_error(
|
|
200
|
-
"The `elements` key is set in the configuration, but its value"
|
|
201
|
-
" is `None`. It is likely that there is an empty `elements` "
|
|
202
|
-
"section in the yaml configuration file."
|
|
203
|
-
)
|
|
204
80
|
return elements
|
|
205
81
|
|
|
206
82
|
|
|
@@ -2,13 +2,13 @@ with: junifer.testing.registry
|
|
|
2
2
|
workdir: /tmp
|
|
3
3
|
|
|
4
4
|
datagrabber:
|
|
5
|
-
kind:
|
|
6
|
-
elements: [
|
|
5
|
+
kind: UCLACNPVBMTestingDataGrabber
|
|
6
|
+
elements: [sub-10206, sub-10339]
|
|
7
7
|
markers:
|
|
8
|
-
- name:
|
|
8
|
+
- name: TianxS2_Mean
|
|
9
9
|
kind: ParcelAggregation
|
|
10
|
-
parcellation:
|
|
10
|
+
parcellation: TianxS2x3TxMNInonlinear2009cAsym
|
|
11
11
|
method: mean
|
|
12
12
|
storage:
|
|
13
|
-
kind:
|
|
14
|
-
uri: /Users/fraimondo/dev/tbox/junifer/scratch/db/test.
|
|
13
|
+
kind: HDF5FeatureStorage
|
|
14
|
+
uri: /Users/fraimondo/dev/tbox/junifer/scratch/db/test.hdf5
|
|
@@ -2,19 +2,20 @@ with: junifer.testing.registry
|
|
|
2
2
|
workdir: /tmp
|
|
3
3
|
|
|
4
4
|
datagrabber:
|
|
5
|
-
kind:
|
|
5
|
+
kind: UCLACNPVBMTestingDataGrabber
|
|
6
6
|
markers:
|
|
7
|
-
- name:
|
|
7
|
+
- name: TianxS2_Mean
|
|
8
8
|
kind: ParcelAggregation
|
|
9
|
-
parcellation:
|
|
9
|
+
parcellation: TianxS2x3TxMNInonlinear2009cAsym
|
|
10
10
|
method: mean
|
|
11
11
|
storage:
|
|
12
|
-
kind:
|
|
13
|
-
uri: /Users/fraimondo/dev/tbox/junifer/scratch/db/test.
|
|
12
|
+
kind: HDF5FeatureStorage
|
|
13
|
+
uri: /Users/fraimondo/dev/tbox/junifer/scratch/db/test.hdf5
|
|
14
14
|
queue:
|
|
15
15
|
jobname: TestHTCondorQueue
|
|
16
16
|
kind: HTCondor
|
|
17
17
|
env:
|
|
18
18
|
kind: conda
|
|
19
19
|
name: junifer
|
|
20
|
+
shell: bash
|
|
20
21
|
mem: 8G
|
junifer/cli/tests/test_cli.py
CHANGED
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
5
5
|
# License: AGPL
|
|
6
6
|
|
|
7
|
+
import tempfile
|
|
8
|
+
from collections.abc import Callable
|
|
7
9
|
from pathlib import Path
|
|
8
|
-
from typing import Callable
|
|
9
10
|
|
|
10
11
|
import pytest
|
|
11
12
|
from click.testing import CliRunner
|
|
12
13
|
from ruamel.yaml import YAML
|
|
13
14
|
|
|
14
15
|
from junifer.cli.cli import (
|
|
16
|
+
_parse_yaml,
|
|
15
17
|
collect,
|
|
16
18
|
list_elements,
|
|
17
19
|
queue,
|
|
@@ -20,7 +22,11 @@ from junifer.cli.cli import (
|
|
|
20
22
|
selftest,
|
|
21
23
|
wtf,
|
|
22
24
|
)
|
|
23
|
-
from junifer.cli.parser import _parse_elements_file
|
|
25
|
+
from junifer.cli.parser import _parse_elements_file, parse_elements
|
|
26
|
+
from junifer.pipeline import WorkDirManager
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
pytestmark = pytest.mark.external
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
# Configure YAML class
|
|
@@ -199,6 +205,47 @@ def test_multi_element_access(
|
|
|
199
205
|
assert read_elements == expected_list
|
|
200
206
|
|
|
201
207
|
|
|
208
|
+
@pytest.mark.parametrize(
|
|
209
|
+
"element, config, expected",
|
|
210
|
+
[
|
|
211
|
+
((), {}, None),
|
|
212
|
+
((), {"elements": ["sub-01", "sub-02"]}, ["sub-01", "sub-02"]),
|
|
213
|
+
((), {"elements": "sub-01"}, ["sub-01"]),
|
|
214
|
+
((), {"elements": [["sub-01", "ses-01"]]}, [("sub-01", "ses-01")]),
|
|
215
|
+
(("sub-01", "sub-02,ses-01"), {}, ["sub-01", ("sub-02", "ses-01")]),
|
|
216
|
+
],
|
|
217
|
+
)
|
|
218
|
+
def test_parse_elements(
|
|
219
|
+
element: tuple[str, ...], config: dict, expected: list | None
|
|
220
|
+
) -> None:
|
|
221
|
+
"""Test parsing the elements from the command line or the configuration.
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
element : tuple of str
|
|
226
|
+
The parametrized elements of the command line.
|
|
227
|
+
config : dict
|
|
228
|
+
The parametrized configuration.
|
|
229
|
+
expected : list or None
|
|
230
|
+
The parametrized elements to expect.
|
|
231
|
+
|
|
232
|
+
"""
|
|
233
|
+
assert parse_elements(element, config) == expected
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def test_parse_elements_command_line_precedence() -> None:
|
|
237
|
+
"""Test the elements of the command line have precedence."""
|
|
238
|
+
with pytest.warns(RuntimeWarning, match="command line has precedence"):
|
|
239
|
+
elements = parse_elements(("sub-01",), {"elements": ["sub-02"]})
|
|
240
|
+
assert elements == ["sub-01"]
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_parse_elements_empty_config() -> None:
|
|
244
|
+
"""Test an empty elements key in the configuration."""
|
|
245
|
+
with pytest.raises(ValueError, match="its value is `None`"):
|
|
246
|
+
parse_elements((), {"elements": None})
|
|
247
|
+
|
|
248
|
+
|
|
202
249
|
def test_queue(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
203
250
|
"""Test queue command.
|
|
204
251
|
|
|
@@ -219,7 +266,7 @@ def test_queue(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
219
266
|
# Working directory
|
|
220
267
|
contents["workdir"] = str(tmp_path.resolve())
|
|
221
268
|
# Storage
|
|
222
|
-
contents["storage"]["uri"] = str((tmp_path / "out.
|
|
269
|
+
contents["storage"]["uri"] = str((tmp_path / "out.hdf5").resolve())
|
|
223
270
|
# Write new test config
|
|
224
271
|
outfile = tmp_path / "in.yaml"
|
|
225
272
|
yaml.dump(contents, stream=outfile)
|
|
@@ -271,7 +318,7 @@ def test_reset(
|
|
|
271
318
|
# Working directory
|
|
272
319
|
contents["workdir"] = str(tmp_path.resolve())
|
|
273
320
|
# Storage
|
|
274
|
-
contents["storage"]["uri"] = str((tmp_path / "out.
|
|
321
|
+
contents["storage"]["uri"] = str((tmp_path / "out.hdf5").resolve())
|
|
275
322
|
# Write new test config
|
|
276
323
|
outfile = tmp_path / "in.yaml"
|
|
277
324
|
yaml.dump(contents, stream=outfile)
|
|
@@ -380,6 +427,75 @@ def test_list_elements_output_file(
|
|
|
380
427
|
assert f"{elements[0]}\n{elements[1]}" == f.read()
|
|
381
428
|
|
|
382
429
|
|
|
430
|
+
@pytest.mark.parametrize(
|
|
431
|
+
"workdir, expected",
|
|
432
|
+
[
|
|
433
|
+
("workdir", "workdir"),
|
|
434
|
+
({"path": "workdir", "cleanup": False}, "workdir"),
|
|
435
|
+
(None, "junifer"),
|
|
436
|
+
],
|
|
437
|
+
ids=["path", "dict", "default"],
|
|
438
|
+
)
|
|
439
|
+
def test_parse_yaml_workdir(
|
|
440
|
+
tmp_path: Path,
|
|
441
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
442
|
+
workdir: str | dict | None,
|
|
443
|
+
expected: str,
|
|
444
|
+
) -> None:
|
|
445
|
+
"""Test the working directory is set up when parsing the YAML.
|
|
446
|
+
|
|
447
|
+
Parameters
|
|
448
|
+
----------
|
|
449
|
+
tmp_path : pathlib.Path
|
|
450
|
+
The path to the test directory.
|
|
451
|
+
monkeypatch : pytest.MonkeyPatch
|
|
452
|
+
The pytest.MonkeyPatch object.
|
|
453
|
+
workdir : str or dict or None
|
|
454
|
+
The parametrized working directory in the YAML. If None, the YAML
|
|
455
|
+
has no working directory.
|
|
456
|
+
expected : str
|
|
457
|
+
The parametrized working directory set up, relative to ``tmp_path``.
|
|
458
|
+
|
|
459
|
+
"""
|
|
460
|
+
# Use the test directory for relative paths and as temporary directory,
|
|
461
|
+
# where the default working directory is
|
|
462
|
+
monkeypatch.chdir(tmp_path)
|
|
463
|
+
monkeypatch.setattr(tempfile, "tempdir", str(tmp_path))
|
|
464
|
+
contents = {"datagrabber": {"kind": "PartlyCloudyTestingDataGrabber"}}
|
|
465
|
+
if workdir is not None:
|
|
466
|
+
contents["workdir"] = workdir
|
|
467
|
+
yaml.dump(contents, stream=tmp_path / "in.yaml")
|
|
468
|
+
# The configuration is not changed
|
|
469
|
+
assert _parse_yaml(tmp_path / "in.yaml") == contents # type: ignore
|
|
470
|
+
assert WorkDirManager().workdir.resolve() == tmp_path / expected
|
|
471
|
+
assert (tmp_path / expected).is_dir()
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def test_list_elements_workdir(tmp_path: Path) -> None:
|
|
475
|
+
"""Test elements listing in the working directory of the YAML.
|
|
476
|
+
|
|
477
|
+
Parameters
|
|
478
|
+
----------
|
|
479
|
+
tmp_path : pathlib.Path
|
|
480
|
+
The path to the test directory.
|
|
481
|
+
|
|
482
|
+
"""
|
|
483
|
+
# Get test config
|
|
484
|
+
infile = Path(__file__).parent / "data" / "partly_cloudy_agg_mean_tian.yml"
|
|
485
|
+
contents = yaml.load(infile)
|
|
486
|
+
# Working directory
|
|
487
|
+
workdir = tmp_path / "workdir"
|
|
488
|
+
contents["workdir"] = str(workdir)
|
|
489
|
+
# Write new test config
|
|
490
|
+
outfile = tmp_path / "in.yaml"
|
|
491
|
+
yaml.dump(contents, stream=outfile)
|
|
492
|
+
# Invoke list elements command
|
|
493
|
+
list_elements_result = runner.invoke(list_elements, [str(outfile)])
|
|
494
|
+
# Check
|
|
495
|
+
assert list_elements_result.exit_code == 0
|
|
496
|
+
assert WorkDirManager().workdir == workdir
|
|
497
|
+
|
|
498
|
+
|
|
383
499
|
def test_wtf_short() -> None:
|
|
384
500
|
"""Test short version of wtf command."""
|
|
385
501
|
# Invoke wtf command
|