Coverage for python/lsst/ctrl/mpexec/cli/opt/options.py: 77%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

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# (https://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 

22import click 

23from lsst.daf.butler.cli.utils import MWOptionDecorator, MWPath, split_commas, unwrap 

24 

25 

26def _split_commas_int(context, param, values): 

27 """Special callback that handles comma-separated list of integers. 

28 

29 Parameters 

30 ---------- 

31 context : `click.Context` or `None` 

32 The current execution context. 

33 param : `click.core.Option` or `None` 

34 The parameter being handled. 

35 values : `list` [ `str` ] 

36 All the values passed for this option. Strings may contain commas, 

37 which will be treated as delimiters for separate values. 

38 

39 Returns 

40 ------- 

41 numbers : `tuple` [ `int` ] 

42 The passed in values separated by commas and combined into a single 

43 list. 

44 """ 

45 

46 def _to_int(value): 

47 """Convert string to integer, handle errors.""" 

48 try: 

49 return int(value) 

50 except ValueError: 

51 raise click.BadParameter(f"'{value}' is not a valid integer", context, param) 

52 

53 values = split_commas(context, param, values) 

54 if values is None: 

55 return values 

56 return tuple(_to_int(value) for value in values) 

57 

58 

59butler_config_option = MWOptionDecorator( 

60 "-b", "--butler-config", help="Location of the gen3 butler/registry config file." 

61) 

62 

63 

64data_query_option = MWOptionDecorator( 

65 "-d", "--data-query", help="User data selection expression.", metavar="QUERY" 

66) 

67 

68 

69debug_option = MWOptionDecorator( 

70 "--debug", help="Enable debugging output using lsstDebug facility (imports debug.py).", is_flag=True 

71) 

72 

73 

74delete_option = MWOptionDecorator( 

75 "--delete", callback=split_commas, help="Delete task with given label from pipeline.", multiple=True 

76) 

77 

78 

79pdb_option = MWOptionDecorator( 

80 "--pdb", 

81 help="Post-mortem debugger to launch for exceptions (defaults to pdb if unspecified; requires a tty).", 

82 is_flag=False, 

83 flag_value="pdb", 

84 default=None, 

85) 

86 

87 

88extend_run_option = MWOptionDecorator( 

89 "--extend-run", 

90 help=unwrap( 

91 """Instead of creating a new RUN collection, insert datasets 

92 into either the one given by --output-run (if provided) or 

93 the first child collection of --output (which must be of 

94 type RUN). This also enables --skip-existing option.""" 

95 ), 

96 is_flag=True, 

97) 

98 

99 

100graph_fixup_option = MWOptionDecorator( 

101 "--graph-fixup", 

102 help=unwrap( 

103 """Name of the class or factory method which makes an 

104 instance used for execution graph fixup.""" 

105 ), 

106) 

107 

108 

109init_only_option = MWOptionDecorator( 

110 "--init-only", 

111 help=unwrap( 

112 """Do not actually run; just register dataset types and/or 

113 save init outputs. """ 

114 ), 

115 is_flag=True, 

116) 

117 

118 

119input_option = MWOptionDecorator( 

120 "-i", 

121 "--input", 

122 callback=split_commas, 

123 default=list(), 

124 help=unwrap("""Comma-separated names of the input collection(s)."""), 

125 metavar="COLLECTION", 

126 multiple=True, 

127) 

128 

129no_versions_option = MWOptionDecorator( 

130 "--no-versions", help="Do not save or check package versions.", is_flag=True 

131) 

132 

133 

134order_pipeline_option = MWOptionDecorator( 

135 "--order-pipeline", 

136 help=unwrap( 

137 """Order tasks in pipeline based on their data 

138 dependencies, ordering is performed as last step before saving or 

139 executing pipeline.""" 

140 ), 

141 is_flag=True, 

142) 

143 

144 

145output_option = MWOptionDecorator( 

146 "-o", 

147 "--output", 

148 help=unwrap( 

149 """Name of the output CHAINED collection. This may either be an 

150 existing CHAINED collection to use as both input and output 

151 (incompatible with --input), or a new CHAINED collection created 

152 to include all inputs (requires --input). In both cases, the 

153 collection's children will start with an output RUN collection 

154 that directly holds all new datasets (see --output-run).""" 

155 ), 

156 metavar="COLL", 

157) 

158 

159 

160output_run_option = MWOptionDecorator( 

161 "--output-run", 

162 help=unwrap( 

163 """Name of the new output RUN collection. If not provided 

164 then --output must be provided and a new RUN collection will 

165 be created by appending a timestamp to the value passed with 

166 --output. If this collection already exists then 

167 --extend-run must be passed.""" 

168 ), 

169 metavar="COLL", 

170) 

171 

172 

173pipeline_option = MWOptionDecorator( 

174 "-p", 

175 "--pipeline", 

176 help="Location of a pipeline definition file in YAML format.", 

177 type=MWPath(file_okay=True, dir_okay=False, readable=True), 

178) 

179 

180 

181pipeline_dot_option = MWOptionDecorator( 

182 "--pipeline-dot", 

183 help=unwrap( 

184 """"Location for storing GraphViz DOT representation of a 

185 pipeline.""" 

186 ), 

187 type=MWPath(writable=True, file_okay=True, dir_okay=False), 

188) 

189 

190 

191profile_option = MWOptionDecorator( 

192 "--profile", help="Dump cProfile statistics to file name.", type=MWPath(file_okay=True, dir_okay=False) 

193) 

194 

195 

196prune_replaced_option = MWOptionDecorator( 

197 "--prune-replaced", 

198 help=unwrap( 

199 """Delete the datasets in the collection replaced by 

200 --replace-run, either just from the datastore 

201 ('unstore') or by removing them and the RUN completely 

202 ('purge'). Requires --replace-run.""" 

203 ), 

204 type=click.Choice(("unstore", "purge"), case_sensitive=False), 

205) 

206 

207 

208qgraph_option = MWOptionDecorator( 

209 "-g", 

210 "--qgraph", 

211 help=unwrap( 

212 """Location for a serialized quantum graph definition (pickle 

213 file). If this option is given then all input data options and 

214 pipeline-building options cannot be used. Can be a URI.""" 

215 ), 

216) 

217 

218 

219qgraph_id_option = MWOptionDecorator( 

220 "--qgraph-id", 

221 help=unwrap( 

222 """Quantum graph identifier, if specified must match the 

223 identifier of the graph loaded from a file. Ignored if graph 

224 is not loaded from a file.""" 

225 ), 

226) 

227 

228 

229# I wanted to use default=None here to match Python API but click silently 

230# replaces None with an empty tuple when multiple=True. 

231qgraph_node_id_option = MWOptionDecorator( 

232 "--qgraph-node-id", 

233 callback=split_commas, 

234 multiple=True, 

235 help=unwrap( 

236 """Only load a specified set of nodes when graph is 

237 loaded from a file, nodes are identified by UUID 

238 values. One or more comma-separated integers are 

239 accepted. By default all nodes are loaded. Ignored if 

240 graph is not loaded from a file.""" 

241 ), 

242) 

243 

244qgraph_header_data_option = MWOptionDecorator( 

245 "--show-qgraph-header", 

246 is_flag=True, 

247 default=False, 

248 help=unwrap( 

249 """Print the headerData for Quantum Graph to the 

250 console""" 

251 ), 

252) 

253 

254qgraph_dot_option = MWOptionDecorator( 

255 "--qgraph-dot", 

256 help=unwrap( 

257 """Location for storing GraphViz DOT representation of a 

258 quantum graph.""" 

259 ), 

260 type=MWPath(writable=True, file_okay=True, dir_okay=False), 

261) 

262 

263 

264replace_run_option = MWOptionDecorator( 

265 "--replace-run", 

266 help=unwrap( 

267 """Before creating a new RUN collection in an existing 

268 CHAINED collection, remove the first child collection 

269 (which must be of type RUN). This can be used to repeatedly 

270 write to the same (parent) collection during development, 

271 but it does not delete the datasets associated with the 

272 replaced run unless --prune-replaced is also passed. 

273 Requires --output, and incompatible with --extend-run.""" 

274 ), 

275 is_flag=True, 

276) 

277 

278 

279save_pipeline_option = MWOptionDecorator( 

280 "-s", 

281 "--save-pipeline", 

282 help=unwrap( 

283 """Location for storing resulting pipeline definition in 

284 YAML format.""" 

285 ), 

286 type=MWPath(dir_okay=False, file_okay=True, writable=True), 

287) 

288 

289save_qgraph_option = MWOptionDecorator( 

290 "-q", 

291 "--save-qgraph", 

292 help=unwrap( 

293 """URI location for storing a serialized quantum graph 

294 definition (pickle file).""" 

295 ), 

296) 

297 

298 

299save_single_quanta_option = MWOptionDecorator( 

300 "--save-single-quanta", 

301 help=unwrap( 

302 """Format string of locations for storing individual 

303 quantum graph definition (pickle files). The curly 

304 brace {} in the input string will be replaced by a 

305 quantum number. Can be a URI.""" 

306 ), 

307) 

308 

309 

310show_option = MWOptionDecorator( 

311 "--show", 

312 callback=split_commas, 

313 help=unwrap( 

314 """Dump various info to standard output. Possible items are: 

315 `config`, `config=[Task::]<PATTERN>` or 

316 `config=[Task::]<PATTERN>:NOIGNORECASE` to dump configuration 

317 fields possibly matching given pattern and/or task label; 

318 `history=<FIELD>` to dump configuration history for a field, field 

319 name is specified as [Task::]<PATTERN>; `dump-config`, 

320 `dump-config=Task` to dump complete configuration for a task given 

321 its label or all tasks; `pipeline` to show pipeline composition; 

322 `graph` to show information about quanta; `workflow` to show 

323 information about quanta and their dependency; `tasks` to show 

324 task composition; `uri` to show predicted dataset URIs of 

325 quanta""" 

326 ), 

327 metavar="ITEM|ITEM=VALUE", 

328 multiple=True, 

329) 

330 

331 

332skip_existing_in_option = MWOptionDecorator( 

333 "--skip-existing-in", 

334 callback=split_commas, 

335 default=None, 

336 metavar="COLLECTION", 

337 multiple=True, 

338 help=unwrap( 

339 """If all Quantum outputs already exist in the specified list of 

340 collections then that Quantum will be excluded from the QuantumGraph. 

341 """ 

342 ), 

343) 

344 

345 

346skip_existing_option = MWOptionDecorator( 

347 "--skip-existing", 

348 is_flag=True, 

349 help=unwrap( 

350 """This option is equivalent to --skip-existing-in with the name of 

351 the output RUN collection. If both --skip-existing-in and 

352 --skip-existing are given then output RUN collection is appended to 

353 the list of collections.""" 

354 ), 

355) 

356 

357 

358clobber_outputs_option = MWOptionDecorator( 

359 "--clobber-outputs", 

360 help=unwrap( 

361 """Remove outputs from previous execution of the same 

362 quantum before new execution. If --skip-existing 

363 is also passed, then only failed quanta will be 

364 clobbered. Requires the 'run' command's --extend-run 

365 flag to be set.""" 

366 ), 

367 is_flag=True, 

368) 

369 

370 

371skip_init_writes_option = MWOptionDecorator( 

372 "--skip-init-writes", 

373 help=unwrap( 

374 """Do not write collection-wide 'init output' datasets 

375 (e.g.schemas).""" 

376 ), 

377 is_flag=True, 

378) 

379 

380 

381task_option = MWOptionDecorator( 

382 "-t", 

383 "--task", 

384 callback=split_commas, 

385 help=unwrap( 

386 """Task name to add to pipeline, must be a fully qualified task 

387 name. Task name can be followed by colon and label name, if label 

388 is not given then task base name (class name) is used as 

389 label.""" 

390 ), 

391 metavar="TASK[:LABEL]", 

392 multiple=True, 

393) 

394 

395 

396timeout_option = MWOptionDecorator( 

397 "--timeout", type=click.IntRange(min=0), help="Timeout for multiprocessing; maximum wall time (sec)." 

398) 

399 

400 

401start_method_option = MWOptionDecorator( 

402 "--start-method", 

403 default=None, 

404 type=click.Choice(["spawn", "fork", "forkserver"]), 

405 help="Multiprocessing start method, default is platform-specific.", 

406) 

407 

408 

409fail_fast_option = MWOptionDecorator( 

410 "--fail-fast", 

411 help=unwrap( 

412 """Stop processing at first error, default is to process 

413 as many tasks as possible.""" 

414 ), 

415 is_flag=True, 

416) 

417 

418save_execution_butler_option = MWOptionDecorator( 

419 "--save-execution-butler", 

420 help=unwrap( 

421 """Export location for an 

422 execution-specific butler after making 

423 QuantumGraph""" 

424 ), 

425) 

426 

427mock_option = MWOptionDecorator( 

428 "--mock", 

429 help=unwrap("""Mock pipeline execution."""), 

430 is_flag=True, 

431) 

432 

433clobber_execution_butler_option = MWOptionDecorator( 

434 "--clobber-execution-butler", 

435 help=unwrap( 

436 """When creating execution butler overwrite 

437 any existing products""" 

438 ), 

439 is_flag=True, 

440) 

441dataset_query_constraint = MWOptionDecorator( 

442 "--dataset-query-constraint", 

443 help=unwrap( 

444 """When constructing a quantum graph constrain by 

445 pre-existence of specified dataset types. Valid 

446 values are `all` for all inputs dataset types in 

447 pipeline, `off` to not consider dataset type 

448 existance as a constraint, single or comma 

449 separated list of dataset type names""" 

450 ), 

451 default="all", 

452) 

453 

454summary_option = MWOptionDecorator( 

455 "--summary", 

456 help=( 

457 "Location for storing job summary (JSON file). Note that the" 

458 " structure of this file may not be stable." 

459 ), 

460 type=MWPath(dir_okay=False, file_okay=True, writable=True), 

461)