Skip to content

Commit d715aff

Browse files
authored
Prevent commands which take Tasks IDs taking Job IDs. (#6130)
1 parent 62527e0 commit d715aff

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

changes.d/6130.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent commands accepting job IDs where it doesn't make sense.

cylc/flow/command_validation.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818

1919

2020
from typing import (
21+
Iterable,
2122
List,
2223
Optional,
2324
)
2425

2526
from cylc.flow.exceptions import InputError
26-
from cylc.flow.id import Tokens
27+
from cylc.flow.id import IDTokens, Tokens
2728
from cylc.flow.task_outputs import TASK_OUTPUT_SUCCEEDED
2829
from cylc.flow.flow_mgr import FLOW_ALL, FLOW_NEW, FLOW_NONE
2930

@@ -228,3 +229,35 @@ def consistency(
228229
"""
229230
if outputs and prereqs:
230231
raise InputError("Use --prerequisite or --output, not both.")
232+
233+
234+
def is_tasks(tasks: Iterable[str]):
235+
"""All tasks in a list of tasks are task ID's without trailing job ID.
236+
237+
Examples:
238+
# All legal
239+
>>> is_tasks(['1/foo', '1/bar', '*/baz', '*/*'])
240+
241+
# Some legal
242+
>>> is_tasks(['1/foo/NN', '1/bar', '*/baz', '*/*/42'])
243+
Traceback (most recent call last):
244+
...
245+
cylc.flow.exceptions.InputError: This command does not take job ids:
246+
* 1/foo/NN
247+
* */*/42
248+
249+
# None legal
250+
>>> is_tasks(['*/baz/12'])
251+
Traceback (most recent call last):
252+
...
253+
cylc.flow.exceptions.InputError: This command does not take job ids:
254+
* */baz/12
255+
"""
256+
bad_tasks: List[str] = []
257+
for task in tasks:
258+
tokens = Tokens('//' + task)
259+
if tokens.lowest_token == IDTokens.Job.value:
260+
bad_tasks.append(task)
261+
if bad_tasks:
262+
msg = 'This command does not take job ids:\n * '
263+
raise InputError(msg + '\n * '.join(bad_tasks))

cylc/flow/commands.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ async def set_prereqs_and_outputs(
145145
outputs = validate.outputs(outputs)
146146
prerequisites = validate.prereqs(prerequisites)
147147
validate.flow_opts(flow, flow_wait)
148+
validate.is_tasks(tasks)
148149

149150
yield
150151

@@ -172,6 +173,8 @@ async def stop(
172173
task: Optional[str] = None,
173174
flow_num: Optional[int] = None,
174175
):
176+
if task:
177+
validate.is_tasks([task])
175178
yield
176179
if flow_num:
177180
schd.pool.stop_flow(flow_num)
@@ -214,6 +217,7 @@ async def stop(
214217
@_command('release')
215218
async def release(schd: 'Scheduler', tasks: Iterable[str]):
216219
"""Release held tasks."""
220+
validate.is_tasks(tasks)
217221
yield
218222
yield schd.pool.release_held_tasks(tasks)
219223

@@ -237,6 +241,7 @@ async def resume(schd: 'Scheduler'):
237241
@_command('poll_tasks')
238242
async def poll_tasks(schd: 'Scheduler', tasks: Iterable[str]):
239243
"""Poll pollable tasks or a task or family if options are provided."""
244+
validate.is_tasks(tasks)
240245
yield
241246
if schd.get_run_mode() == RunMode.SIMULATION:
242247
yield 0
@@ -248,6 +253,7 @@ async def poll_tasks(schd: 'Scheduler', tasks: Iterable[str]):
248253
@_command('kill_tasks')
249254
async def kill_tasks(schd: 'Scheduler', tasks: Iterable[str]):
250255
"""Kill all tasks or a task/family if options are provided."""
256+
validate.is_tasks(tasks)
251257
yield
252258
itasks, _, bad_items = schd.pool.filter_task_proxies(tasks)
253259
if schd.get_run_mode() == RunMode.SIMULATION:
@@ -264,6 +270,7 @@ async def kill_tasks(schd: 'Scheduler', tasks: Iterable[str]):
264270
@_command('hold')
265271
async def hold(schd: 'Scheduler', tasks: Iterable[str]):
266272
"""Hold specified tasks."""
273+
validate.is_tasks(tasks)
267274
yield
268275
yield schd.pool.hold_tasks(tasks)
269276

@@ -304,6 +311,7 @@ async def set_verbosity(schd: 'Scheduler', level: Union[int, str]):
304311
@_command('remove_tasks')
305312
async def remove_tasks(schd: 'Scheduler', tasks: Iterable[str]):
306313
"""Remove tasks."""
314+
validate.is_tasks(tasks)
307315
yield
308316
yield schd.pool.remove_tasks(tasks)
309317

@@ -430,5 +438,6 @@ async def force_trigger_tasks(
430438
flow_descr: Optional[str] = None,
431439
):
432440
"""Manual task trigger."""
441+
validate.is_tasks(tasks)
433442
yield
434443
yield schd.pool.force_trigger_tasks(tasks, flow, flow_wait, flow_descr)

0 commit comments

Comments
 (0)