|
9 | 9 |
|
10 | 10 | from typing import Any, Optional |
11 | 11 |
|
12 | | -from cwl_utils.parser import WorkflowStep, save |
| 12 | +from cwl_utils.parser import save |
13 | 13 | from cwl_utils.parser.cwl_v1_2 import ( |
14 | 14 | CommandLineTool, |
15 | 15 | ExpressionTool, |
@@ -186,65 +186,38 @@ def validate_production(cls, values): |
186 | 186 | # Temporary code, waiting on cwltool PR: https://github.com/common-workflow-language/cwltool/pull/2179. |
187 | 187 |
|
188 | 188 |
|
189 | | -def validate_resource_requirements(task): |
190 | | - """ |
191 | | - Validate ResourceRequirements of a task (CommandLineTool, Workflow, WorkflowStep, WorkflowStep.run). |
| 189 | +def validate_resource_requirements(task: CommandLineTool | Workflow | ExpressionTool): |
| 190 | + """Validate ResourceRequirements of a task recursively. |
192 | 191 |
|
193 | | - :param task: The task to validate |
| 192 | + :param task: The task to validate. |
| 193 | + :raises ValueError: If any ResourceRequirement has min > max. |
194 | 194 | """ |
195 | | - cwl_req = _get_resource_requirement(task) |
196 | | - |
197 | | - # Validate Workflow/CLT requirements. |
198 | | - if cwl_req: |
199 | | - _validate_resource_requirement(cwl_req) |
200 | | - |
201 | | - # Validate WorkflowStep requirements. |
202 | | - if not isinstance(task, CommandLineTool) and task.steps: |
203 | | - for step in task.steps: |
204 | | - step_req = _get_resource_requirement(step) |
205 | | - if step_req: |
206 | | - _validate_resource_requirement(step_req) |
207 | | - |
208 | | - # Validate run requirements for each step if they exist. |
| 195 | + # Validate task-level requirements |
| 196 | + for req in getattr(task, "requirements", None) or []: |
| 197 | + if isinstance(req, ResourceRequirement): |
| 198 | + _validate_min_max(req) |
| 199 | + |
| 200 | + # Recurse into workflow steps |
| 201 | + if isinstance(task, Workflow): |
| 202 | + for step in task.steps or []: |
| 203 | + for req in getattr(step, "requirements", None) or []: |
| 204 | + if isinstance(req, ResourceRequirement): |
| 205 | + _validate_min_max(req) |
209 | 206 | if step.run: |
210 | | - if isinstance(step.run, Workflow): |
211 | | - # Validate nested Workflow requirements, if any. |
212 | | - validate_resource_requirements(task=step.run) |
213 | | - |
214 | | - step_run_req = _get_resource_requirement(step.run) |
215 | | - if step_run_req: |
216 | | - _validate_resource_requirement(step_run_req) |
217 | | - |
| 207 | + validate_resource_requirements(step.run) |
218 | 208 |
|
219 | | -def _validate_resource_requirement(requirement): |
220 | | - """Validate a ResourceRequirement. |
221 | 209 |
|
222 | | - Verify that resourceMin is not higher than resourceMax (CommandLineTool, Workflow, WorkflowStep, WorkflowStep.run) |
| 210 | +def _validate_min_max(req: ResourceRequirement): |
| 211 | + """Check that min does not exceed max for any resource. |
223 | 212 |
|
224 | | - :param requirement: The current ResourceRequirement to validate. |
225 | | - :raises ValueError: If the requirement is invalid. |
| 213 | + :param req: The ResourceRequirement to validate. |
| 214 | + :raises ValueError: If min > max for any resource. |
226 | 215 | """ |
227 | | - for resource, min_value, max_value in [ |
228 | | - ("ram", requirement.ramMin, requirement.ramMax), |
229 | | - ("cores", requirement.coresMin, requirement.coresMax), |
230 | | - ("tmpdir", requirement.tmpdirMin, requirement.tmpdirMax), |
231 | | - ("outdir", requirement.outdirMin, requirement.outdirMax), |
| 216 | + for name, lo, hi in [ |
| 217 | + ("cores", req.coresMin, req.coresMax), |
| 218 | + ("ram", req.ramMin, req.ramMax), |
| 219 | + ("tmpdir", req.tmpdirMin, req.tmpdirMax), |
| 220 | + ("outdir", req.outdirMin, req.outdirMax), |
232 | 221 | ]: |
233 | | - if min_value and max_value and min_value > max_value: |
234 | | - raise ValueError(f"{resource}Min is higher than {resource}Max") |
235 | | - |
236 | | - |
237 | | -def _get_resource_requirement( |
238 | | - cwl_object: Workflow | CommandLineTool | WorkflowStep, |
239 | | -) -> ResourceRequirement | None: |
240 | | - """ |
241 | | - Extract the resource requirement from the current cwl_object. |
242 | | -
|
243 | | - :param cwl_object: The cwl_object to extract the requirement from. |
244 | | - :return: The resource requirement object, or None if not found. |
245 | | - """ |
246 | | - requirements = getattr(cwl_object, "requirements", []) or [] |
247 | | - for requirement in requirements: |
248 | | - if isinstance(requirement, ResourceRequirement): |
249 | | - return requirement |
250 | | - return None |
| 222 | + if lo and hi and lo > hi: |
| 223 | + raise ValueError(f"{name}Min ({lo}) exceeds {name}Max ({hi})") |
0 commit comments