53
53
"""
54
54
55
55
from contextlib import suppress
56
- from time import sleep , time
56
+ from time import (
57
+ sleep ,
58
+ time ,
59
+ )
57
60
from typing import (
61
+ TYPE_CHECKING ,
58
62
AsyncGenerator ,
59
63
Callable ,
60
64
Dict ,
61
65
Iterable ,
62
66
List ,
63
67
Optional ,
64
- TYPE_CHECKING ,
68
+ TypeVar ,
65
69
Union ,
66
70
)
67
71
72
+ from metomi .isodatetime .parsers import TimePointParser
73
+
68
74
from cylc .flow import LOG
69
75
import cylc .flow .command_validation as validate
70
76
from cylc .flow .exceptions import (
73
79
CylcConfigError ,
74
80
)
75
81
import cylc .flow .flags
82
+ from cylc .flow .flow_mgr import get_flow_nums_set
76
83
from cylc .flow .log_level import log_level_to_verbosity
77
84
from cylc .flow .network .schema import WorkflowStopMode
78
85
from cylc .flow .parsec .exceptions import ParsecError
79
86
from cylc .flow .task_id import TaskID
80
- from cylc .flow .workflow_status import RunMode , StopMode
87
+ from cylc .flow .workflow_status import (
88
+ RunMode ,
89
+ StopMode ,
90
+ )
81
91
82
- from metomi .isodatetime .parsers import TimePointParser
83
92
84
93
if TYPE_CHECKING :
85
94
from cylc .flow .scheduler import Scheduler
86
95
87
96
# define a type for command implementations
88
- Command = Callable [
89
- ...,
90
- AsyncGenerator ,
91
- ]
97
+ Command = Callable [..., AsyncGenerator ]
98
+ # define a generic type needed for the @_command decorator
99
+ _TCommand = TypeVar ('_TCommand' , bound = Command )
92
100
93
101
# a directory of registered commands (populated on module import)
94
102
COMMANDS : 'Dict[str, Command]' = {}
95
103
96
104
97
105
def _command (name : str ):
98
106
"""Decorator to register a command."""
99
- def _command (fcn : 'Command' ) :
107
+ def _command (fcn : '_TCommand' ) -> '_TCommand' :
100
108
nonlocal name
101
109
COMMANDS [name ] = fcn
102
- fcn .command_name = name # type: ignore
110
+ fcn .command_name = name # type: ignore[attr-defined]
103
111
return fcn
104
112
return _command
105
113
106
114
107
- async def run_cmd (fcn , * args , ** kwargs ):
115
+ async def run_cmd (bound_fcn : AsyncGenerator ):
108
116
"""Run a command outside of the scheduler's main loop.
109
117
110
118
Normally commands are run via the Scheduler's command_queue (which is
@@ -119,10 +127,9 @@ async def run_cmd(fcn, *args, **kwargs):
119
127
For these purposes use "run_cmd", otherwise, queue commands via the
120
128
scheduler as normal.
121
129
"""
122
- cmd = fcn (* args , ** kwargs )
123
- await cmd .__anext__ () # validate
130
+ await bound_fcn .__anext__ () # validate
124
131
with suppress (StopAsyncIteration ):
125
- return await cmd .__anext__ () # run
132
+ return await bound_fcn .__anext__ () # run
126
133
127
134
128
135
@_command ('set' )
@@ -310,11 +317,15 @@ async def set_verbosity(schd: 'Scheduler', level: Union[int, str]):
310
317
311
318
312
319
@_command ('remove_tasks' )
313
- async def remove_tasks (schd : 'Scheduler' , tasks : Iterable [str ]):
320
+ async def remove_tasks (
321
+ schd : 'Scheduler' , tasks : Iterable [str ], flow : List [str ]
322
+ ):
314
323
"""Remove tasks."""
315
324
validate .is_tasks (tasks )
325
+ validate .flow_opts (flow , flow_wait = False , allow_new_or_none = False )
316
326
yield
317
- yield schd .pool .remove_tasks (tasks )
327
+ flow_nums = get_flow_nums_set (flow )
328
+ schd .remove_tasks (tasks , flow_nums )
318
329
319
330
320
331
@_command ('reload_workflow' )
0 commit comments