|
3 | 3 | """ |
4 | 4 |
|
5 | 5 | import re |
| 6 | +from pathlib import Path |
6 | 7 | from snakemake_interface_common.exceptions import WorkflowError |
7 | 8 |
|
8 | 9 |
|
@@ -73,3 +74,68 @@ def validate_slurm_extra(job): |
73 | 74 | f"specification instead. " |
74 | 75 | f"Consult the documentation for proper resource configuration." |
75 | 76 | ) |
| 77 | + |
| 78 | + |
| 79 | +def validate_executor_settings(settings): |
| 80 | + """ |
| 81 | + Validate ExecutorSettings fields for correctness |
| 82 | + (better user feedback in case of wrong inputs) |
| 83 | +
|
| 84 | + Args: |
| 85 | + settings: ExecutorSettins instance to validate |
| 86 | +
|
| 87 | + Raises: |
| 88 | + WorkflowError - if any validation check fails |
| 89 | + """ |
| 90 | + # status_command: only allow known values |
| 91 | + if settings.status_command is not None: |
| 92 | + if settings.status_command not in {"sacct", "squeue"}: |
| 93 | + raise WorkflowError( |
| 94 | + "Invalid status command. Allowed values are 'sacct' or 'squeue'." |
| 95 | + ) |
| 96 | + |
| 97 | + # status_attempts: require positive integer |
| 98 | + if settings.status_attempts is not None: |
| 99 | + if ( |
| 100 | + not isinstance(settings.status_attempts, int) |
| 101 | + or settings.status_attempts < 1 |
| 102 | + ): |
| 103 | + raise WorkflowError("status_attempts must be a positive integer") |
| 104 | + |
| 105 | + # init_settings_befor_status_checks: require non-negative integer |
| 106 | + if settings.init_seconds_before_status_checks is not None: |
| 107 | + if ( |
| 108 | + not isinstance(settings.init_seconds_before_status_checks, int) |
| 109 | + or settings.init_seconds_before_status_checks < 0 |
| 110 | + ): |
| 111 | + raise WorkflowError( |
| 112 | + "init-seconds-before-status-checks must be a positive integer." |
| 113 | + ) |
| 114 | + |
| 115 | + # efficiency_threshold, if set must be within (0, 1] |
| 116 | + if settings.efficiency_threshold is not None: |
| 117 | + try: |
| 118 | + thr = float(settings.efficiency_threshold) |
| 119 | + except (TypeError, ValueError): |
| 120 | + raise WorkflowError( |
| 121 | + "efficiency-threshold must be a number in range (0, 1]." |
| 122 | + ) |
| 123 | + if not (0 < thr <= 1.0): |
| 124 | + raise WorkflowError( |
| 125 | + "efficiency-threshold must be a number in range (0, 1]." |
| 126 | + ) |
| 127 | + |
| 128 | + # partition_config: if provided, it must exist |
| 129 | + if settings.partition_config is not None: |
| 130 | + p = Path(settings.partition_config) |
| 131 | + if not p.exists(): |
| 132 | + raise WorkflowError( |
| 133 | + f"Partition configuration file not found, given was {p}." |
| 134 | + ) |
| 135 | + |
| 136 | + # delete_logfiles_older_than: if provided, should be reasonable |
| 137 | + if settings.delete_logfiles_older_than is not None: |
| 138 | + if not isinstance(settings.delete_logfiles_older_than, int): |
| 139 | + raise WorkflowError( |
| 140 | + "delete-logfiles-older-than must be an integer (days)." |
| 141 | + ) |
0 commit comments