Coverage for python/lsst/ctrl/mpexec/cli/cmd/commands.py: 83%

69 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-26 09:46 +0000

1# This file is part of ctrl_mpexec. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22from functools import partial 

23 

24import click 

25import lsst.pipe.base.cli.opt as pipeBaseOpts 

26from lsst.daf.butler.cli.opt import config_file_option, config_option, confirm_option, options_file_option 

27from lsst.daf.butler.cli.utils import MWCtxObj, catch_and_exit, option_section, unwrap 

28 

29from .. import opt as ctrlMpExecOpts 

30from .. import script 

31from ..script import confirmable 

32from ..utils import _ACTION_CONFIG, _ACTION_CONFIG_FILE, PipetaskCommand, makePipelineActions 

33 

34epilog = unwrap( 

35 """Notes: 

36 

37--task, --delete, --config, --config-file, and --instrument action options can 

38appear multiple times; all values are used, in order left to right. 

39 

40FILE reads command-line options from the specified file. Data may be 

41distributed among multiple lines (e.g. one option per line). Data after # is 

42treated as a comment and ignored. Blank lines and lines starting with # are 

43ignored.) 

44""" 

45) 

46 

47 

48def _collectActions(ctx, **kwargs): 

49 """Extract pipeline building options, replace them with PipelineActions, 

50 return updated `kwargs`. 

51 

52 Notes 

53 ----- 

54 The pipeline actions (task, delete, config, config_file, and instrument) 

55 must be handled in the order they appear on the command line, but the CLI 

56 specification gives them all different option names. So, instead of using 

57 the individual action options as they appear in kwargs (because 

58 invocation order can't be known), we capture the CLI arguments by 

59 overriding `click.Command.parse_args` and save them in the Context's 

60 `obj` parameter. We use `makePipelineActions` to create a list of 

61 pipeline actions from the CLI arguments and pass that list to the script 

62 function using the `pipeline_actions` kwarg name, and remove the action 

63 options from kwargs. 

64 """ 

65 for pipelineAction in ( 

66 ctrlMpExecOpts.task_option.name(), 

67 ctrlMpExecOpts.delete_option.name(), 

68 config_option.name(), 

69 config_file_option.name(), 

70 pipeBaseOpts.instrument_option.name(), 

71 ): 

72 kwargs.pop(pipelineAction) 

73 

74 actions = makePipelineActions(MWCtxObj.getFrom(ctx).args) 

75 mock_configs = [] 

76 pipeline_actions = [] 

77 for action in actions: 

78 if action.label and action.label.endswith("-mock"): 78 ↛ 79line 78 didn't jump to line 79, because the condition on line 78 was never true

79 if action.action not in (_ACTION_CONFIG.action, _ACTION_CONFIG_FILE.action): 

80 raise ValueError(f"Unexpected option for mock task config overrides: {action}") 

81 mock_configs.append(action) 

82 else: 

83 pipeline_actions.append(action) 

84 

85 kwargs["mock_configs"] = mock_configs 

86 kwargs["pipeline_actions"] = pipeline_actions 

87 return kwargs 

88 

89 

90@click.command(cls=PipetaskCommand, epilog=epilog, short_help="Build pipeline definition.") 

91@click.pass_context 

92@ctrlMpExecOpts.show_option() 

93@ctrlMpExecOpts.pipeline_build_options() 

94@option_section(sectionText="") 

95@options_file_option() 

96@catch_and_exit 

97def build(ctx, **kwargs): 

98 """Build and optionally save pipeline definition. 

99 

100 This does not require input data to be specified. 

101 """ 

102 kwargs = _collectActions(ctx, **kwargs) 

103 script.build(**kwargs) 

104 

105 

106@click.command(cls=PipetaskCommand, epilog=epilog) 

107@click.pass_context 

108@ctrlMpExecOpts.show_option() 

109@ctrlMpExecOpts.pipeline_build_options() 

110@ctrlMpExecOpts.qgraph_options() 

111@ctrlMpExecOpts.butler_options() 

112@option_section(sectionText="") 

113@options_file_option() 

114@catch_and_exit 

115def qgraph(ctx, **kwargs): 

116 """Build and optionally save quantum graph.""" 

117 kwargs = _collectActions(ctx, **kwargs) 

118 pipeline = script.build(**kwargs) 

119 script.qgraph(pipelineObj=pipeline, **kwargs) 

120 

121 

122@click.command(cls=PipetaskCommand, epilog=epilog) 

123@ctrlMpExecOpts.run_options() 

124@catch_and_exit 

125def run(ctx, **kwargs): 

126 """Build and execute pipeline and quantum graph.""" 

127 kwargs = _collectActions(ctx, **kwargs) 

128 pipeline = script.build(**kwargs) 

129 qgraph = script.qgraph(pipelineObj=pipeline, **kwargs) 

130 script.run(qgraphObj=qgraph, **kwargs) 

131 

132 

133@click.command(cls=PipetaskCommand) 

134@ctrlMpExecOpts.butler_config_option() 

135@ctrlMpExecOpts.collection_argument() 

136@confirm_option() 

137@ctrlMpExecOpts.recursive_option( 

138 help="""If the parent CHAINED collection has child CHAINED collections, 

139 search the children until nested chains that start with the parent's name 

140 are removed.""" 

141) 

142def purge(confirm, **kwargs): 

143 """Remove a CHAINED collection and its contained collections. 

144 

145 COLLECTION is the name of the chained collection to purge. it must not be a 

146 child of any other CHAINED collections 

147 

148 Child collections must be members of exactly one collection. 

149 

150 The collections that will be removed will be printed, there will be an 

151 option to continue or abort (unless using --no-confirm). 

152 """ 

153 confirmable.confirm(partial(script.purge, **kwargs), confirm) 

154 

155 

156@click.command(cls=PipetaskCommand) 

157@ctrlMpExecOpts.butler_config_option() 

158@ctrlMpExecOpts.collection_argument() 

159@confirm_option() 

160def cleanup(confirm, **kwargs): 

161 """Remove non-members of CHAINED collections. 

162 

163 Removes collections that start with the same name as a CHAINED 

164 collection but are not members of that collection. 

165 """ 

166 confirmable.confirm(partial(script.cleanup, **kwargs), confirm)