Skip to content

Commit 569797d

Browse files
committed
Replicated original set-outputs behaviour. [skip ci]
1 parent b6053f7 commit 569797d

File tree

14 files changed

+80
-74
lines changed

14 files changed

+80
-74
lines changed

cylc/flow/etc/cylc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
44
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
5-
#
5+
#
66
# This program is free software: you can redistribute it and/or modify
77
# it under the terms of the GNU General Public License as published by
88
# the Free Software Foundation, either version 3 of the License, or

cylc/flow/network/resolvers.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,9 @@ def force_spawn_children(
811811
self,
812812
tasks: Iterable[str],
813813
outputs: Optional[Iterable[str]] = None,
814-
flow_num: Optional[int] = None
814+
flow: Iterable[str] = None,
815+
flow_wait: bool = False,
816+
flow_descr: str = ""
815817
) -> Tuple[bool, str]:
816818
"""Spawn children of given task outputs.
817819
@@ -820,15 +822,18 @@ def force_spawn_children(
820822
Args:
821823
tasks: List of identifiers or task globs.
822824
outputs: List of outputs to spawn on.
823-
flow_num: Flow number to attribute the outputs.
825+
flow (list):
826+
Flow ownership of triggered tasks.
824827
"""
825828
self.schd.command_queue.put(
826829
(
827830
"force_spawn_children",
828831
(tasks,),
829832
{
830833
"outputs": outputs,
831-
"flow_num": flow_num
834+
"flow": flow,
835+
"flow_wait": flow_wait,
836+
"flow_descr": flow_descr,
832837
},
833838
)
834839
)

cylc/flow/network/schema.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -2091,25 +2091,33 @@ class Meta:
20912091

20922092
class SetTask(Mutation, TaskMutation):
20932093
class Meta:
2094-
description = sstrip('''
2095-
Intervene in task prerequisite, output, and completion status.
2094+
description = sstrip("""
2095+
Set task prerequisites or outputs.
20962096
2097-
Setting a prerequisite contributes to the task's readiness to run.
2097+
By default, set all required outputs for target task(s).
20982098
2099-
Setting an output contributes to the task's completion, and sets
2100-
the corresponding prerequisites of child tasks.
2099+
Setting prerequisites contributes to the task's readiness to run.
21012100
2102-
Valid for: paused, running workflows.
2103-
''')
2101+
Setting outputs contributes to the task's completion, and sets the
2102+
corresponding prerequisites of child tasks.
2103+
2104+
Setting an output also sets any implied outputs:
2105+
- started implies submitted
2106+
- succeeded and failed imply started
2107+
- custom outputs and expired do not imply any other outputs
2108+
""")
21042109
resolver = partial(mutator, command='force_spawn_children')
21052110

2106-
class Arguments(TaskMutation.Arguments):
2111+
class Arguments(TaskMutation.Arguments, FlowMutationArguments):
21072112
outputs = graphene.List(
21082113
String,
21092114
default_value=[TASK_OUTPUT_SUCCEEDED],
2110-
description='List of task outputs to satisfy.'
2115+
description='List of task outputs to set complete.'
2116+
)
2117+
prerequisites = graphene.List(
2118+
String,
2119+
description='List of task prerequisites to set satisfied.'
21112120
)
2112-
flow_num = Int()
21132121

21142122

21152123
class Trigger(Mutation, TaskMutation):

cylc/flow/scheduler.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -2124,13 +2124,16 @@ def command_force_trigger_tasks(self, items, flow, flow_wait, flow_descr):
21242124
return self.pool.force_trigger_tasks(
21252125
items, flow, flow_wait, flow_descr)
21262126

2127-
def command_force_spawn_children(self, items, outputs, flow_num):
2127+
def command_force_spawn_children(
2128+
self, items, outputs, flow, flow_wait, flow_descr
2129+
):
21282130
"""Force spawn task successors.
21292131
21302132
User-facing method name: set_task.
2131-
21322133
"""
2133-
return self.pool.force_spawn_children(items, outputs, flow_num)
2134+
return self.pool.force_spawn_children(
2135+
items, outputs, flow, flow_wait, flow_descr
2136+
)
21342137

21352138
def _update_profile_info(self, category, amount, amount_format="%s"):
21362139
"""Update the 1, 5, 15 minute dt averages for a given category."""

cylc/flow/scripts/set_task.py

+6-24
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def get_option_parser() -> COP:
9090
)
9191

9292
parser.add_option(
93-
"-o", "--out", metavar="OUTPUT(s)",
93+
"-o", "--out", "--output", metavar="OUTPUT(s)",
9494
help=(
9595
"Set task outputs completed, along with any implied outputs."
9696
' May be "all", to set all required outputs complete.'
@@ -100,7 +100,7 @@ def get_option_parser() -> COP:
100100
)
101101

102102
parser.add_option(
103-
"-p", "--pre", metavar="PREREQUISITE(s)",
103+
"-p", "--pre", "--prerequisite", metavar="PREREQUISITE(s)",
104104
help=(
105105
"Set task prerequisites satisfied."
106106
' May be "all", which is equivalent to "cylc trigger".'
@@ -116,7 +116,7 @@ def get_option_parser() -> COP:
116116
" If the task is already spawned, use current flows and"
117117
" merge new flow numbers if specified."
118118
),
119-
action="store", default=None, dest="flow_num"
119+
action="store", default=None, dest="flow"
120120
)
121121

122122
parser.add_option(
@@ -134,26 +134,6 @@ def get_option_parser() -> COP:
134134
return parser
135135

136136

137-
def _validate(options):
138-
"""Check validity of flow-related options."""
139-
for val in options.flow:
140-
val = val.strip()
141-
if val in [FLOW_NONE, FLOW_NEW, FLOW_ALL]:
142-
if len(options.flow) != 1:
143-
raise InputError(ERR_OPT_FLOW_INT)
144-
else:
145-
try:
146-
int(val)
147-
except ValueError:
148-
raise InputError(ERR_OPT_FLOW_VAL.format(val))
149-
150-
if options.flow_descr and options.flow != [FLOW_NEW]:
151-
raise InputError(ERR_OPT_FLOW_META)
152-
153-
if options.flow_wait and options.flow[0] in [FLOW_NEW, FLOW_NONE]:
154-
raise InputError(ERR_OPT_FLOW_WAIT)
155-
156-
157137
async def run(options: 'Values', workflow_id: str, *tokens_list) -> None:
158138
pclient = get_client(workflow_id, timeout=options.comms_timeout)
159139

@@ -167,7 +147,9 @@ async def run(options: 'Values', workflow_id: str, *tokens_list) -> None:
167147
],
168148
'outputs': options.outputs,
169149
'prerequisites': options.prerequisites,
170-
'flowNum': options.flow_num
150+
'flow': options.flow,
151+
'flowWait': options.flow_wait,
152+
'flowDescr': options.flow_descr
171153
}
172154
}
173155

cylc/flow/scripts/trigger.py

-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ async def run(options: 'Values', workflow_id: str, *tokens_list):
136136
'flowDescr': options.flow_descr,
137137
}
138138
}
139-
140139
await pclient.async_request('graphql', mutation_kwargs)
141140

142141

cylc/flow/task_pool.py

+32-24
Original file line numberDiff line numberDiff line change
@@ -1579,8 +1579,10 @@ def spawn_task(
15791579
def force_spawn_children(
15801580
self,
15811581
items: Iterable[str],
1582-
outputs: Optional[List[str]] = None,
1583-
flow_num: Optional[int] = None
1582+
outputs: List[str],
1583+
flow: List[str],
1584+
flow_wait: bool = False,
1585+
flow_descr: str = "",
15841586
):
15851587
"""Spawn downstream children of given outputs, on user command.
15861588
@@ -1591,14 +1593,13 @@ def force_spawn_children(
15911593
items: Identifiers for matching task definitions, each with the
15921594
form "point/name".
15931595
outputs: List of outputs to spawn on
1594-
flow_num: Flow number to attribute the outputs
1596+
flow: Flow number to attribute the outputs
15951597
15961598
"""
15971599
outputs = outputs or [TASK_OUTPUT_SUCCEEDED]
1598-
if flow_num is None:
1599-
flow_nums = None
1600-
else:
1601-
flow_nums = {flow_num}
1600+
flow_nums = self._flow_cmd_helper(flow)
1601+
if flow_nums is None:
1602+
return
16021603

16031604
n_warnings, task_items = self.match_taskdefs(items)
16041605
for (_, point), taskdef in sorted(task_items.items()):
@@ -1638,27 +1639,15 @@ def remove_tasks(self, items):
16381639
self.release_runahead_tasks()
16391640
return len(bad_items)
16401641

1641-
def force_trigger_tasks(
1642-
self, items: Iterable[str],
1643-
flow: List[str],
1644-
flow_wait: bool = False,
1645-
flow_descr: Optional[str] = None
1646-
) -> int:
1647-
"""Manual task triggering.
1648-
1649-
Don't get a new flow number for existing n=0 tasks (e.g. incomplete
1650-
tasks). These can carry on in the original flow if retriggered.
1651-
1652-
Queue the task if not queued, otherwise release it to run.
1653-
1654-
"""
1642+
def _flow_cmd_helper(self, flow):
1643+
# TODO type hints
16551644
if set(flow).intersection({FLOW_ALL, FLOW_NEW, FLOW_NONE}):
16561645
if len(flow) != 1:
16571646
LOG.warning(
16581647
f'The "flow" values {FLOW_ALL}, {FLOW_NEW} & {FLOW_NONE}'
16591648
' cannot be used in combination with integer flow numbers.'
16601649
)
1661-
return 0
1650+
return None
16621651
if flow[0] == FLOW_ALL:
16631652
flow_nums = self._get_active_flow_nums()
16641653
elif flow[0] == FLOW_NEW:
@@ -1670,9 +1659,28 @@ def force_trigger_tasks(
16701659
flow_nums = {int(n) for n in flow}
16711660
except ValueError:
16721661
LOG.warning(
1673-
f"Trigger ignored, illegal flow values {flow}"
1662+
f"Ignoring command: illegal flow values {flow}"
16741663
)
1675-
return 0
1664+
return None
1665+
return flow_nums
1666+
1667+
def force_trigger_tasks(
1668+
self, items: Iterable[str],
1669+
flow: List[str],
1670+
flow_wait: bool = False,
1671+
flow_descr: Optional[str] = None
1672+
) -> int:
1673+
"""Manual task triggering.
1674+
1675+
Don't get a new flow number for existing n=0 tasks (e.g. incomplete
1676+
tasks). These can carry on in the original flow if retriggered.
1677+
1678+
Queue the task if not queued, otherwise release it to run.
1679+
1680+
"""
1681+
flow_nums = self._flow_cmd_helper(flow)
1682+
if flow_nums is None:
1683+
return
16761684

16771685
# n_warnings, task_items = self.match_taskdefs(items)
16781686
itasks, future_tasks, unmatched = self.filter_task_proxies(

tests/functional/events/23-workflow-stalled-handler/flow.cylc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[scheduler]
22
[[events]]
3-
stall handlers = "cylc set-task --flow=1 %(workflow)s//1/bar"
3+
stall handlers = "cylc set-task %(workflow)s//1/bar"
44
stall timeout = PT0S
55
abort on stall timeout = False
66
expected task failures = 1/bar

tests/functional/logging/02-duplicates/flow.cylc

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
script = false
2323
[[bar]]
2424
script = """
25-
cylc set-task --flow=1 "${CYLC_WORKFLOW_ID}" "foo.${CYLC_TASK_CYCLE_POINT}"
25+
cylc set-task "${CYLC_WORKFLOW_ID}" "foo.${CYLC_TASK_CYCLE_POINT}"
2626
"""
2727
[[restart]]
2828
script = """

tests/functional/reload/17-graphing-change.t

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ cp "${TEST_SOURCE_DIR}/graphing-change/flow-2.cylc" \
6666
"${RUN_DIR}/${WORKFLOW_NAME}/flow.cylc"
6767

6868
# Spawn a couple of task proxies, to get "task definition removed" message.
69-
cylc set-task --flow=1 "${WORKFLOW_NAME}//1/foo"
70-
cylc set-task --flow=1 "${WORKFLOW_NAME}//1/baz"
69+
cylc set-task "${WORKFLOW_NAME}//1/foo"
70+
cylc set-task "${WORKFLOW_NAME}//1/baz"
7171
# reload workflow
7272
run_ok "${TEST_NAME_BASE}-swap-reload" cylc reload "${WORKFLOW_NAME}"
7373
poll grep_workflow_log_n_times 'Reload completed' 3

tests/functional/runahead/default-future/flow.cylc

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
[[spawner]]
2828
script = """
2929
# spawn wibble
30-
cylc set-task --flow=1 $CYLC_WORKFLOW_ID 20100101T0800Z/foo
30+
cylc set-task $CYLC_WORKFLOW_ID 20100101T0800Z/foo
3131
"""
3232
[[foo]]
3333
script = false

tests/functional/spawn-on-demand/12-set-outputs-no-reflow.t tests/functional/spawn-on-demand/12-set-outputs-cont-flow.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
#-------------------------------------------------------------------------------
1818

19-
# Check that "cylc set-task" works like it says on the tin.
19+
# Check that "cylc set-task" continues a flow by default.
2020
. "$(dirname "$0")/test_header"
2121
set_test_number 2
2222
reftest

tests/functional/spawn-on-demand/12-set-outputs-no-reflow/flow.cylc tests/functional/spawn-on-demand/12-set-outputs-cont-flow/flow.cylc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Test that `cylc set-task` does not cause reflow by default
2-
# Task setter should cause bar to run, but not subsequently baz.
1+
# Test that `cylc set-task` continues the active flow by default
2+
# Task setter should cause bar to run, then subsequently baz.
33

44
[scheduler]
55
[[events]]

tests/functional/spawn-on-demand/12-set-outputs-no-reflow/reference.log tests/functional/spawn-on-demand/12-set-outputs-cont-flow/reference.log

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ Final point: 1
33
1/foo -triggered off []
44
1/setter -triggered off ['1/foo']
55
1/bar -triggered off ['1/foo']
6+
1/baz -triggered off ['1/bar']

0 commit comments

Comments
 (0)