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
|
@@ -5,15 +5,38 @@
|
|
|
5
5
|
|
|
6
6
|
import shutil
|
|
7
7
|
import textwrap
|
|
8
|
+
from enum import StrEnum
|
|
8
9
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
10
|
+
from typing import Any
|
|
10
11
|
|
|
11
12
|
from ...typing import Elements
|
|
12
|
-
from ...utils import
|
|
13
|
-
from .queue_context_adapter import
|
|
13
|
+
from ...utils import make_executable, raise_error, run_ext_cmd
|
|
14
|
+
from .queue_context_adapter import (
|
|
15
|
+
EnvKind,
|
|
16
|
+
EnvShell,
|
|
17
|
+
QueueContextAdapter,
|
|
18
|
+
QueueContextEnv,
|
|
19
|
+
logger,
|
|
20
|
+
)
|
|
14
21
|
|
|
15
22
|
|
|
16
|
-
__all__ = ["HTCondorAdapter"]
|
|
23
|
+
__all__ = ["HTCondorAdapter", "HTCondorCollect"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class HTCondorCollect(StrEnum):
|
|
27
|
+
"""Accepted HTCondor collect commands.
|
|
28
|
+
|
|
29
|
+
* ``"yes"``: Submit "collect" task and run even if some of the jobs
|
|
30
|
+
fail.
|
|
31
|
+
* ``"on_success_only"``: Submit "collect" task and run only if all jobs
|
|
32
|
+
succeed.
|
|
33
|
+
* ``"no"``: Do not submit "collect" task.
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
Yes = "yes"
|
|
38
|
+
No = "no"
|
|
39
|
+
OnSuccessOnly = "on_success_only"
|
|
17
40
|
|
|
18
41
|
|
|
19
42
|
class HTCondorAdapter(QueueContextAdapter):
|
|
@@ -27,14 +50,14 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
27
50
|
The path to the job directory.
|
|
28
51
|
yaml_config_path : pathlib.Path
|
|
29
52
|
The path to the YAML config file.
|
|
30
|
-
elements :
|
|
53
|
+
elements : ``Elements``
|
|
31
54
|
Element(s) to process. Will be used to index the DataGrabber.
|
|
32
55
|
pre_run : str or None, optional
|
|
33
|
-
Extra
|
|
56
|
+
Extra shell commands to source before the run (default None).
|
|
34
57
|
pre_collect : str or None, optional
|
|
35
|
-
Extra
|
|
36
|
-
env :
|
|
37
|
-
The
|
|
58
|
+
Extra shell commands to source before the collect (default None).
|
|
59
|
+
env : :class:`.QueueContextEnv` or None, optional
|
|
60
|
+
The environment configuration. If None, will run without a
|
|
38
61
|
virtual environment of any kind (default None).
|
|
39
62
|
verbose : str, optional
|
|
40
63
|
The level of verbosity (default "info").
|
|
@@ -49,25 +72,12 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
49
72
|
The size of disk (HDD or SSD) to use (default "1G").
|
|
50
73
|
extra_preamble : str or None, optional
|
|
51
74
|
Extra commands to pass to HTCondor (default None).
|
|
52
|
-
|
|
75
|
+
collect_task : :class:`.HTCondorCollect`, optional
|
|
53
76
|
Whether to submit "collect" task for junifer (default "yes").
|
|
54
|
-
Valid options are:
|
|
55
|
-
|
|
56
|
-
* "yes": Submit "collect" task and run even if some of the jobs
|
|
57
|
-
fail.
|
|
58
|
-
* "on_success_only": Submit "collect" task and run only if all jobs
|
|
59
|
-
succeed.
|
|
60
|
-
* "no": Do not submit "collect" task.
|
|
61
|
-
|
|
62
77
|
submit : bool, optional
|
|
63
78
|
Whether to submit the jobs. In any case, .dag files will be created
|
|
64
79
|
for submission (default False).
|
|
65
80
|
|
|
66
|
-
Raises
|
|
67
|
-
------
|
|
68
|
-
ValueError
|
|
69
|
-
If ``collect`` is invalid or if ``env`` is invalid.
|
|
70
|
-
|
|
71
81
|
See Also
|
|
72
82
|
--------
|
|
73
83
|
QueueContextAdapter :
|
|
@@ -77,144 +87,67 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
77
87
|
|
|
78
88
|
"""
|
|
79
89
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
self._job_dir = job_dir
|
|
101
|
-
self._yaml_config_path = yaml_config_path
|
|
102
|
-
self._elements = elements
|
|
103
|
-
self._pre_run = pre_run
|
|
104
|
-
self._pre_collect = pre_collect
|
|
105
|
-
self._check_env(env)
|
|
106
|
-
self._verbose = verbose
|
|
107
|
-
self._verbose_datalad = verbose_datalad
|
|
108
|
-
self._cpus = cpus
|
|
109
|
-
self._mem = mem
|
|
110
|
-
self._disk = disk
|
|
111
|
-
self._extra_preamble = extra_preamble
|
|
112
|
-
self._collect = self._check_collect(collect)
|
|
113
|
-
self._submit = submit
|
|
114
|
-
|
|
115
|
-
self._log_dir = self._job_dir / "logs"
|
|
116
|
-
self._pre_run_path = self._job_dir / "pre_run.sh"
|
|
117
|
-
self._pre_collect_path = self._job_dir / "pre_collect.sh"
|
|
118
|
-
self._submit_run_path = self._job_dir / f"run_{self._job_name}.submit"
|
|
119
|
-
self._submit_collect_path = (
|
|
120
|
-
self._job_dir / f"collect_{self._job_name}.submit"
|
|
121
|
-
)
|
|
122
|
-
self._dag_path = self._job_dir / f"{self._job_name}.dag"
|
|
123
|
-
|
|
124
|
-
def _check_env(self, env: Optional[dict[str, str]]) -> None:
|
|
125
|
-
"""Check value of env parameter on init.
|
|
126
|
-
|
|
127
|
-
Parameters
|
|
128
|
-
----------
|
|
129
|
-
env : dict or None
|
|
130
|
-
The value of env parameter.
|
|
131
|
-
|
|
132
|
-
Raises
|
|
133
|
-
------
|
|
134
|
-
ValueError
|
|
135
|
-
If ``env.kind`` is invalid or
|
|
136
|
-
if ``env.shell`` is invalid.
|
|
137
|
-
|
|
138
|
-
"""
|
|
139
|
-
# Set env related variables
|
|
140
|
-
if env is None:
|
|
141
|
-
env = {"kind": "local"}
|
|
142
|
-
# Check env kind
|
|
143
|
-
valid_env_kinds = ["conda", "venv", "local"]
|
|
144
|
-
if env["kind"] not in valid_env_kinds:
|
|
145
|
-
raise_error(
|
|
146
|
-
f"Invalid value for `env.kind`: {env['kind']}, "
|
|
147
|
-
f"must be one of {valid_env_kinds}"
|
|
90
|
+
job_name: str
|
|
91
|
+
job_dir: Path
|
|
92
|
+
yaml_config_path: Path
|
|
93
|
+
elements: Elements
|
|
94
|
+
pre_run: str | None = None
|
|
95
|
+
pre_collect: str | None = None
|
|
96
|
+
env: QueueContextEnv | None = None
|
|
97
|
+
verbose: str = "info"
|
|
98
|
+
verbose_datalad: str | None = None
|
|
99
|
+
cpus: int = 1
|
|
100
|
+
mem: str = "8G"
|
|
101
|
+
disk: str = "1G"
|
|
102
|
+
extra_preamble: str | None = None
|
|
103
|
+
collect_task: HTCondorCollect = HTCondorCollect.Yes
|
|
104
|
+
submit: bool = False
|
|
105
|
+
|
|
106
|
+
def model_post_init(self, context: Any): # noqa: D102
|
|
107
|
+
if self.env is None:
|
|
108
|
+
self.env = QueueContextEnv(
|
|
109
|
+
kind=EnvKind.Local, shell=EnvShell.Bash, name=""
|
|
148
110
|
)
|
|
111
|
+
if self.env["kind"] == EnvKind.Local:
|
|
112
|
+
# No virtual environment
|
|
113
|
+
self._executable = "junifer"
|
|
114
|
+
self._arguments = ""
|
|
149
115
|
else:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
self._arguments = ""
|
|
164
|
-
else:
|
|
165
|
-
self._executable = f"run_{env['kind']}.{self._shell}"
|
|
166
|
-
self._arguments = f"{env['name']} junifer"
|
|
167
|
-
self._exec_path = self._job_dir / self._executable
|
|
168
|
-
|
|
169
|
-
def _check_collect(self, collect: str) -> str:
|
|
170
|
-
"""Check value of collect parameter on init.
|
|
171
|
-
|
|
172
|
-
Parameters
|
|
173
|
-
----------
|
|
174
|
-
collect : str
|
|
175
|
-
The value of collect parameter.
|
|
176
|
-
|
|
177
|
-
Returns
|
|
178
|
-
-------
|
|
179
|
-
str
|
|
180
|
-
The checked value of collect parameter.
|
|
181
|
-
|
|
182
|
-
Raises
|
|
183
|
-
------
|
|
184
|
-
ValueError
|
|
185
|
-
If ``collect`` is invalid.
|
|
186
|
-
|
|
187
|
-
"""
|
|
188
|
-
valid_options = ["yes", "no", "on_success_only"]
|
|
189
|
-
if collect not in valid_options:
|
|
190
|
-
raise_error(
|
|
191
|
-
f"Invalid value for `collect`: {collect}, "
|
|
192
|
-
f"must be one of {valid_options}"
|
|
193
|
-
)
|
|
194
|
-
else:
|
|
195
|
-
return collect
|
|
116
|
+
if self.env["name"] is None:
|
|
117
|
+
raise_error("`env.name` is required")
|
|
118
|
+
self._executable = f"run_{self.env['kind']}.{self.env['shell']}"
|
|
119
|
+
self._arguments = f"{self.env['name']} junifer"
|
|
120
|
+
self._exec_path = self.job_dir / self._executable
|
|
121
|
+
self._log_dir = self.job_dir / "logs"
|
|
122
|
+
self._pre_run_path = self.job_dir / "pre_run.sh"
|
|
123
|
+
self._pre_collect_path = self.job_dir / "pre_collect.sh"
|
|
124
|
+
self._submit_run_path = self.job_dir / f"run_{self.job_name}.submit"
|
|
125
|
+
self._submit_collect_path = (
|
|
126
|
+
self.job_dir / f"collect_{self.job_name}.submit"
|
|
127
|
+
)
|
|
128
|
+
self._dag_path = self.job_dir / f"{self.job_name}.dag"
|
|
196
129
|
|
|
197
|
-
def
|
|
130
|
+
def pre_run_cmds(self) -> str:
|
|
198
131
|
"""Return pre-run commands."""
|
|
199
132
|
fixed = (
|
|
200
|
-
f"#!/usr/bin/env {self.
|
|
133
|
+
f"#!/usr/bin/env {self.env['shell']}\n\n"
|
|
201
134
|
"# This script is auto-generated by junifer.\n\n"
|
|
202
135
|
"# Force datalad to run in non-interactive mode\n"
|
|
203
136
|
"DATALAD_UI_INTERACTIVE=false\n"
|
|
204
137
|
)
|
|
205
|
-
var = self.
|
|
138
|
+
var = self.pre_run or ""
|
|
206
139
|
return fixed + "\n" + var
|
|
207
140
|
|
|
208
|
-
def
|
|
141
|
+
def run_cmds(self) -> str:
|
|
209
142
|
"""Return run commands."""
|
|
210
|
-
verbose_args = f"--verbose {self.
|
|
211
|
-
if self.
|
|
143
|
+
verbose_args = f"--verbose {self.verbose} "
|
|
144
|
+
if self.verbose_datalad is not None:
|
|
212
145
|
verbose_args = (
|
|
213
|
-
f"{verbose_args} --verbose-datalad {self.
|
|
146
|
+
f"{verbose_args} --verbose-datalad {self.verbose_datalad} "
|
|
214
147
|
)
|
|
215
148
|
junifer_run_args = (
|
|
216
149
|
"run "
|
|
217
|
-
f"{self.
|
|
150
|
+
f"{self.yaml_config_path.resolve()!s} "
|
|
218
151
|
f"{verbose_args}"
|
|
219
152
|
"--element $(element)"
|
|
220
153
|
)
|
|
@@ -227,11 +160,11 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
227
160
|
"universe = vanilla\n"
|
|
228
161
|
"getenv = True\n\n"
|
|
229
162
|
"# Resources\n"
|
|
230
|
-
f"request_cpus = {self.
|
|
231
|
-
f"request_memory = {self.
|
|
232
|
-
f"request_disk = {self.
|
|
163
|
+
f"request_cpus = {self.cpus}\n"
|
|
164
|
+
f"request_memory = {self.mem}\n"
|
|
165
|
+
f"request_disk = {self.disk}\n\n"
|
|
233
166
|
"# Executable\n"
|
|
234
|
-
f"initial_dir = {self.
|
|
167
|
+
f"initial_dir = {self.job_dir.resolve()!s}\n"
|
|
235
168
|
f"executable = $(initial_dir)/{self._executable}\n"
|
|
236
169
|
f"transfer_executable = False\n\n"
|
|
237
170
|
f"arguments = {self._arguments} {junifer_run_args}\n\n"
|
|
@@ -240,31 +173,31 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
240
173
|
f"output = {log_dir_prefix}.out\n"
|
|
241
174
|
f"error = {log_dir_prefix}.err\n"
|
|
242
175
|
)
|
|
243
|
-
var = self.
|
|
176
|
+
var = self.extra_preamble or ""
|
|
244
177
|
return fixed + "\n" + var + "\n" + "queue"
|
|
245
178
|
|
|
246
|
-
def
|
|
179
|
+
def pre_collect_cmds(self) -> str:
|
|
247
180
|
"""Return pre-collect commands."""
|
|
248
181
|
fixed = (
|
|
249
|
-
f"#!/usr/bin/env {self.
|
|
182
|
+
f"#!/usr/bin/env {self.env['shell']}\n\n"
|
|
250
183
|
"# This script is auto-generated by junifer.\n"
|
|
251
184
|
)
|
|
252
|
-
var = self.
|
|
185
|
+
var = self.pre_collect or ""
|
|
253
186
|
# Add commands if collect="yes"
|
|
254
|
-
if self.
|
|
187
|
+
if self.collect_task == "yes":
|
|
255
188
|
var += 'if [ "${1}" == "4" ]; then\n exit 1\nfi\n'
|
|
256
189
|
return fixed + "\n" + var
|
|
257
190
|
|
|
258
|
-
def
|
|
191
|
+
def collect_cmds(self) -> str:
|
|
259
192
|
"""Return collect commands."""
|
|
260
|
-
verbose_args = f"--verbose {self.
|
|
261
|
-
if self.
|
|
193
|
+
verbose_args = f"--verbose {self.verbose} "
|
|
194
|
+
if self.verbose_datalad is not None:
|
|
262
195
|
verbose_args = (
|
|
263
|
-
f"{verbose_args} --verbose-datalad {self.
|
|
196
|
+
f"{verbose_args} --verbose-datalad {self.verbose_datalad} "
|
|
264
197
|
)
|
|
265
198
|
|
|
266
199
|
junifer_collect_args = (
|
|
267
|
-
f"collect {self.
|
|
200
|
+
f"collect {self.yaml_config_path.resolve()!s} {verbose_args}"
|
|
268
201
|
)
|
|
269
202
|
log_dir_prefix = f"{self._log_dir.resolve()!s}/junifer_collect"
|
|
270
203
|
fixed = (
|
|
@@ -273,11 +206,11 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
273
206
|
"universe = vanilla\n"
|
|
274
207
|
"getenv = True\n\n"
|
|
275
208
|
"# Resources\n"
|
|
276
|
-
f"request_cpus = {self.
|
|
277
|
-
f"request_memory = {self.
|
|
278
|
-
f"request_disk = {self.
|
|
209
|
+
f"request_cpus = {self.cpus}\n"
|
|
210
|
+
f"request_memory = {self.mem}\n"
|
|
211
|
+
f"request_disk = {self.disk}\n\n"
|
|
279
212
|
"# Executable\n"
|
|
280
|
-
f"initial_dir = {self.
|
|
213
|
+
f"initial_dir = {self.job_dir.resolve()!s}\n"
|
|
281
214
|
f"executable = $(initial_dir)/{self._executable}\n"
|
|
282
215
|
"transfer_executable = False\n\n"
|
|
283
216
|
f"arguments = {self._arguments} {junifer_collect_args}\n\n"
|
|
@@ -286,13 +219,13 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
286
219
|
f"output = {log_dir_prefix}.out\n"
|
|
287
220
|
f"error = {log_dir_prefix}.err\n"
|
|
288
221
|
)
|
|
289
|
-
var = self.
|
|
222
|
+
var = self.extra_preamble or ""
|
|
290
223
|
return fixed + "\n" + var + "\n" + "queue"
|
|
291
224
|
|
|
292
|
-
def
|
|
225
|
+
def dag_cmds(self) -> str:
|
|
293
226
|
"""Return HTCondor DAG commands."""
|
|
294
227
|
fixed = ""
|
|
295
|
-
for idx, element in enumerate(self.
|
|
228
|
+
for idx, element in enumerate(self.elements):
|
|
296
229
|
# Stringify elements if tuple for operation
|
|
297
230
|
str_element = (
|
|
298
231
|
",".join(element) if isinstance(element, tuple) else element
|
|
@@ -307,15 +240,15 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
307
240
|
f'log_element="{log_element}"\n\n' # double quoted
|
|
308
241
|
)
|
|
309
242
|
var = ""
|
|
310
|
-
if self.
|
|
243
|
+
if self.collect_task == "yes":
|
|
311
244
|
var += (
|
|
312
245
|
f"FINAL collect {self._submit_collect_path}\n"
|
|
313
246
|
f"SCRIPT PRE collect {self._pre_collect_path.as_posix()} "
|
|
314
247
|
"$DAG_STATUS\n"
|
|
315
248
|
)
|
|
316
|
-
elif self.
|
|
249
|
+
elif self.collect_task == "on_success_only":
|
|
317
250
|
var += f"JOB collect {self._submit_collect_path}\nPARENT "
|
|
318
|
-
for idx, _ in enumerate(self.
|
|
251
|
+
for idx, _ in enumerate(self.elements):
|
|
319
252
|
var += f"run{idx} "
|
|
320
253
|
var += "CHILD collect\n"
|
|
321
254
|
|
|
@@ -326,7 +259,7 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
326
259
|
logger.info("Creating HTCondor job")
|
|
327
260
|
# Create logs
|
|
328
261
|
logger.info(
|
|
329
|
-
f"Creating logs directory under {self.
|
|
262
|
+
f"Creating logs directory under {self.job_dir.resolve()!s}"
|
|
330
263
|
)
|
|
331
264
|
self._log_dir.mkdir(exist_ok=True, parents=True)
|
|
332
265
|
# Copy executable if not local
|
|
@@ -341,46 +274,50 @@ class HTCondorAdapter(QueueContextAdapter):
|
|
|
341
274
|
make_executable(self._exec_path)
|
|
342
275
|
# Create pre run
|
|
343
276
|
logger.info(
|
|
344
|
-
f"Writing {self._pre_run_path.name} to {self.
|
|
277
|
+
f"Writing {self._pre_run_path.name} to {self.job_dir.resolve()!s}"
|
|
345
278
|
)
|
|
346
279
|
self._pre_run_path.touch()
|
|
347
|
-
self._pre_run_path.write_text(textwrap.dedent(self.
|
|
280
|
+
self._pre_run_path.write_text(textwrap.dedent(self.pre_run_cmds()))
|
|
348
281
|
make_executable(self._pre_run_path)
|
|
349
282
|
# Create run
|
|
350
283
|
logger.debug(
|
|
351
284
|
f"Writing {self._submit_run_path.name} to "
|
|
352
|
-
f"{self.
|
|
285
|
+
f"{self.job_dir.resolve()!s}"
|
|
353
286
|
)
|
|
354
287
|
self._submit_run_path.touch()
|
|
355
|
-
self._submit_run_path.write_text(textwrap.dedent(self.
|
|
288
|
+
self._submit_run_path.write_text(textwrap.dedent(self.run_cmds()))
|
|
356
289
|
# Create pre collect
|
|
357
290
|
logger.info(
|
|
358
291
|
f"Writing {self._pre_collect_path.name} to "
|
|
359
|
-
f"{self.
|
|
292
|
+
f"{self.job_dir.resolve()!s}"
|
|
360
293
|
)
|
|
361
294
|
self._pre_collect_path.touch()
|
|
362
|
-
self._pre_collect_path.write_text(
|
|
295
|
+
self._pre_collect_path.write_text(
|
|
296
|
+
textwrap.dedent(self.pre_collect_cmds())
|
|
297
|
+
)
|
|
363
298
|
make_executable(self._pre_collect_path)
|
|
364
299
|
# Create collect
|
|
365
300
|
logger.debug(
|
|
366
301
|
f"Writing {self._submit_collect_path.name} to "
|
|
367
|
-
f"{self.
|
|
302
|
+
f"{self.job_dir.resolve()!s}"
|
|
368
303
|
)
|
|
369
304
|
self._submit_collect_path.touch()
|
|
370
|
-
self._submit_collect_path.write_text(
|
|
305
|
+
self._submit_collect_path.write_text(
|
|
306
|
+
textwrap.dedent(self.collect_cmds())
|
|
307
|
+
)
|
|
371
308
|
# Create DAG
|
|
372
309
|
logger.debug(
|
|
373
|
-
f"Writing {self._dag_path.name} to {self.
|
|
310
|
+
f"Writing {self._dag_path.name} to {self.job_dir.resolve()!s}"
|
|
374
311
|
)
|
|
375
312
|
self._dag_path.touch()
|
|
376
|
-
self._dag_path.write_text(textwrap.dedent(self.
|
|
313
|
+
self._dag_path.write_text(textwrap.dedent(self.dag_cmds()))
|
|
377
314
|
# Submit if required
|
|
378
315
|
condor_submit_dag_cmd = [
|
|
379
316
|
"condor_submit_dag",
|
|
380
317
|
"-include_env HOME",
|
|
381
318
|
f"{self._dag_path.resolve()!s}",
|
|
382
319
|
]
|
|
383
|
-
if self.
|
|
320
|
+
if self.submit:
|
|
384
321
|
run_ext_cmd(name="condor_submit_dag", cmd=condor_submit_dag_cmd)
|
|
385
322
|
else:
|
|
386
323
|
logger.info(
|
|
@@ -3,24 +3,68 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if sys.version_info < (3, 12): # pragma: no cover
|
|
10
|
+
from typing_extensions import TypedDict
|
|
11
|
+
else:
|
|
12
|
+
from typing import TypedDict
|
|
13
|
+
|
|
6
14
|
from abc import ABC, abstractmethod
|
|
15
|
+
from enum import StrEnum
|
|
16
|
+
from typing import Required
|
|
17
|
+
|
|
18
|
+
import structlog
|
|
19
|
+
from pydantic import BaseModel, ConfigDict
|
|
7
20
|
|
|
8
21
|
from ...utils import raise_error
|
|
9
22
|
|
|
10
23
|
|
|
11
|
-
__all__ = ["QueueContextAdapter"]
|
|
24
|
+
__all__ = ["EnvKind", "EnvShell", "QueueContextAdapter", "QueueContextEnv"]
|
|
25
|
+
|
|
26
|
+
_log = structlog.get_logger("junifer")
|
|
27
|
+
logger = _log.bind(pkg="api")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class EnvKind(StrEnum):
|
|
31
|
+
"""Accepted Python environment kind."""
|
|
32
|
+
|
|
33
|
+
Venv = "venv"
|
|
34
|
+
Conda = "conda"
|
|
35
|
+
Local = "local"
|
|
12
36
|
|
|
13
37
|
|
|
14
|
-
class
|
|
38
|
+
class EnvShell(StrEnum):
|
|
39
|
+
"""Accepted environment shell."""
|
|
40
|
+
|
|
41
|
+
Bash = "bash"
|
|
42
|
+
Zsh = "zsh"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class QueueContextEnv(TypedDict, total=False):
|
|
46
|
+
"""Accepted environment configuration for queue context."""
|
|
47
|
+
|
|
48
|
+
kind: Required[EnvKind]
|
|
49
|
+
name: str
|
|
50
|
+
shell: Required[EnvShell]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class QueueContextAdapter(BaseModel, ABC):
|
|
15
54
|
"""Abstract base class for queue context adapter.
|
|
16
55
|
|
|
17
|
-
For every
|
|
56
|
+
For every queue context, one needs to provide a concrete
|
|
18
57
|
implementation of this abstract class.
|
|
19
58
|
|
|
20
59
|
"""
|
|
21
60
|
|
|
61
|
+
model_config = ConfigDict(
|
|
62
|
+
use_enum_values=True,
|
|
63
|
+
extra="forbid",
|
|
64
|
+
)
|
|
65
|
+
|
|
22
66
|
@abstractmethod
|
|
23
|
-
def
|
|
67
|
+
def pre_run_cmds(self) -> str:
|
|
24
68
|
"""Return pre-run commands."""
|
|
25
69
|
raise_error(
|
|
26
70
|
msg="Concrete classes need to implement pre_run()",
|
|
@@ -28,7 +72,7 @@ class QueueContextAdapter(ABC):
|
|
|
28
72
|
)
|
|
29
73
|
|
|
30
74
|
@abstractmethod
|
|
31
|
-
def
|
|
75
|
+
def run_cmds(self) -> str:
|
|
32
76
|
"""Return run commands."""
|
|
33
77
|
raise_error(
|
|
34
78
|
msg="Concrete classes need to implement run()",
|
|
@@ -36,7 +80,7 @@ class QueueContextAdapter(ABC):
|
|
|
36
80
|
)
|
|
37
81
|
|
|
38
82
|
@abstractmethod
|
|
39
|
-
def
|
|
83
|
+
def pre_collect_cmds(self) -> str:
|
|
40
84
|
"""Return pre-collect commands."""
|
|
41
85
|
raise_error(
|
|
42
86
|
msg="Concrete classes need to implement pre_collect()",
|
|
@@ -44,7 +88,7 @@ class QueueContextAdapter(ABC):
|
|
|
44
88
|
)
|
|
45
89
|
|
|
46
90
|
@abstractmethod
|
|
47
|
-
def
|
|
91
|
+
def collect_cmds(self) -> str:
|
|
48
92
|
"""Return collect commands."""
|
|
49
93
|
raise_error(
|
|
50
94
|
msg="Concrete classes need to implement collect()",
|
|
@@ -5,37 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Optional, Union
|
|
9
8
|
|
|
10
9
|
import pytest
|
|
11
10
|
|
|
12
11
|
from junifer.api.queue_context import GnuParallelLocalAdapter
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
def test_GnuParallelLocalAdapter_env_kind_error() -> None:
|
|
16
|
-
"""Test error for invalid env kind."""
|
|
17
|
-
with pytest.raises(ValueError, match=r"Invalid value for `env.kind`"):
|
|
18
|
-
GnuParallelLocalAdapter(
|
|
19
|
-
job_name="check_env_kind",
|
|
20
|
-
job_dir=Path("."),
|
|
21
|
-
yaml_config_path=Path("."),
|
|
22
|
-
elements=["sub01"],
|
|
23
|
-
env={"kind": "jambalaya"},
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def test_GnuParallelLocalAdapter_env_shell_error() -> None:
|
|
28
|
-
"""Test error for invalid env shell."""
|
|
29
|
-
with pytest.raises(ValueError, match=r"Invalid value for `env.shell`"):
|
|
30
|
-
GnuParallelLocalAdapter(
|
|
31
|
-
job_name="check_env_shell",
|
|
32
|
-
job_dir=Path("."),
|
|
33
|
-
yaml_config_path=Path("."),
|
|
34
|
-
elements=["sub01"],
|
|
35
|
-
env={"kind": "conda", "shell": "fish"},
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
14
|
@pytest.mark.parametrize(
|
|
40
15
|
"elements, expected_text",
|
|
41
16
|
[
|
|
@@ -44,7 +19,7 @@ def test_GnuParallelLocalAdapter_env_shell_error() -> None:
|
|
|
44
19
|
],
|
|
45
20
|
)
|
|
46
21
|
def test_GnuParallelLocalAdapter_elements(
|
|
47
|
-
elements: list[
|
|
22
|
+
elements: list[str | tuple],
|
|
48
23
|
expected_text: str,
|
|
49
24
|
) -> None:
|
|
50
25
|
"""Test GnuParallelLocalAdapter elements().
|
|
@@ -63,7 +38,7 @@ def test_GnuParallelLocalAdapter_elements(
|
|
|
63
38
|
yaml_config_path=Path("."),
|
|
64
39
|
elements=elements,
|
|
65
40
|
)
|
|
66
|
-
assert expected_text in adapter.
|
|
41
|
+
assert expected_text in adapter.elements_to_run()
|
|
67
42
|
|
|
68
43
|
|
|
69
44
|
@pytest.mark.parametrize(
|
|
@@ -76,7 +51,7 @@ def test_GnuParallelLocalAdapter_elements(
|
|
|
76
51
|
],
|
|
77
52
|
)
|
|
78
53
|
def test_GnuParallelLocalAdapter_pre_run(
|
|
79
|
-
pre_run:
|
|
54
|
+
pre_run: str | None,
|
|
80
55
|
expected_text: str,
|
|
81
56
|
shell: str,
|
|
82
57
|
) -> None:
|
|
@@ -100,8 +75,8 @@ def test_GnuParallelLocalAdapter_pre_run(
|
|
|
100
75
|
env={"kind": "conda", "name": "junifer", "shell": shell},
|
|
101
76
|
pre_run=pre_run,
|
|
102
77
|
)
|
|
103
|
-
assert shell in adapter.
|
|
104
|
-
assert expected_text in adapter.
|
|
78
|
+
assert shell in adapter.pre_run_cmds()
|
|
79
|
+
assert expected_text in adapter.pre_run_cmds()
|
|
105
80
|
|
|
106
81
|
|
|
107
82
|
@pytest.mark.parametrize(
|
|
@@ -114,7 +89,7 @@ def test_GnuParallelLocalAdapter_pre_run(
|
|
|
114
89
|
],
|
|
115
90
|
)
|
|
116
91
|
def test_GnuParallelLocalAdapter_pre_collect(
|
|
117
|
-
pre_collect:
|
|
92
|
+
pre_collect: str | None,
|
|
118
93
|
expected_text: str,
|
|
119
94
|
shell: str,
|
|
120
95
|
) -> None:
|
|
@@ -138,8 +113,8 @@ def test_GnuParallelLocalAdapter_pre_collect(
|
|
|
138
113
|
env={"kind": "venv", "name": "junifer", "shell": shell},
|
|
139
114
|
pre_collect=pre_collect,
|
|
140
115
|
)
|
|
141
|
-
assert shell in adapter.
|
|
142
|
-
assert expected_text in adapter.
|
|
116
|
+
assert shell in adapter.pre_collect_cmds()
|
|
117
|
+
assert expected_text in adapter.pre_collect_cmds()
|
|
143
118
|
|
|
144
119
|
|
|
145
120
|
def test_GnuParallelLocalAdapter_run() -> None:
|
|
@@ -150,7 +125,7 @@ def test_GnuParallelLocalAdapter_run() -> None:
|
|
|
150
125
|
yaml_config_path=Path("."),
|
|
151
126
|
elements=["sub01"],
|
|
152
127
|
)
|
|
153
|
-
assert "run" in adapter.
|
|
128
|
+
assert "run" in adapter.run_cmds()
|
|
154
129
|
|
|
155
130
|
|
|
156
131
|
def test_GnuParallelLocalAdapter_collect() -> None:
|
|
@@ -161,7 +136,7 @@ def test_GnuParallelLocalAdapter_collect() -> None:
|
|
|
161
136
|
yaml_config_path=Path("."),
|
|
162
137
|
elements=["sub01"],
|
|
163
138
|
)
|
|
164
|
-
assert "collect" in adapter.
|
|
139
|
+
assert "collect" in adapter.collect_cmds()
|
|
165
140
|
|
|
166
141
|
|
|
167
142
|
@pytest.mark.parametrize(
|