Coverage for python/lsst/ctrl/mpexec/singleQuantumExecutor.py: 69%

51 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-21 01:24 -0800

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 software is dual licensed under the GNU General Public License and also 

10# under a 3-clause BSD license. Recipients may choose which of these licenses 

11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, 

12# respectively. If you choose the GPL option then the following text applies 

13# (but note that there is still no warranty even if you opt for BSD instead): 

14# 

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

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

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

18# (at your option) any later version. 

19# 

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

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

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

23# GNU General Public License for more details. 

24# 

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

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

27 

28from __future__ import annotations 

29 

30__all__ = ("SingleQuantumExecutor",) 

31 

32import uuid 

33from collections.abc import Callable, Mapping 

34from typing import TYPE_CHECKING, Any 

35 

36from deprecated.sphinx import deprecated 

37 

38import lsst.pipe.base.single_quantum_executor 

39 

40if TYPE_CHECKING: 

41 from lsst.daf.butler import Butler, ButlerMetrics, LimitedButler, Quantum 

42 from lsst.pipe.base import ExecutionResources, PipelineTask, QuantumSuccessCaveats, TaskFactory 

43 from lsst.pipe.base.pipeline_graph import TaskNode 

44 

45 

46# TODO[DM-51962]: Remove this module. 

47@deprecated( 

48 "The SingleQuantumExecutor class has moved to lsst.pipe.base.single_quantum_executor. " 

49 "This forwarding shim will be removed after v30.", 

50 version="v30", 

51 category=FutureWarning, 

52) 

53class SingleQuantumExecutor(lsst.pipe.base.single_quantum_executor.SingleQuantumExecutor): 

54 """Executor class which runs one Quantum at a time. 

55 

56 This is a deprecated backwards-compatibility shim for 

57 `lsst.pipe.base.single_quantum_executor.SingleQuantumExecutor`, which has 

58 the same functionality with very minor interface changes. 

59 

60 Parameters 

61 ---------- 

62 butler : `~lsst.daf.butler.Butler` or `None` 

63 Data butler, `None` means that Quantum-backed butler should be used 

64 instead. 

65 taskFactory : `~lsst.pipe.base.TaskFactory` 

66 Instance of a task factory. 

67 skipExistingIn : `~typing.Any` 

68 Expressions representing the collections to search for existing output 

69 datasets. See :ref:`daf_butler_ordered_collection_searches` for allowed 

70 types. This class only checks for the presence of butler output run in 

71 the list of collections. If the output run is present in the list then 

72 the quanta whose complete outputs exist in the output run will be 

73 skipped. `None` or empty string/sequence disables skipping. 

74 clobberOutputs : `bool`, optional 

75 If `True`, then outputs from a quantum that exist in output run 

76 collection will be removed prior to executing a quantum. If 

77 ``skipExistingIn`` contains output run, then only partial outputs from 

78 a quantum will be removed. Only used when ``butler`` is not `None`. 

79 enableLsstDebug : `bool`, optional 

80 Enable debugging with ``lsstDebug`` facility for a task. 

81 limited_butler_factory : `Callable`, optional 

82 A method that creates a `~lsst.daf.butler.LimitedButler` instance for a 

83 given Quantum. This parameter must be defined if ``butler`` is `None`. 

84 If ``butler`` is not `None` then this parameter is ignored. 

85 resources : `~lsst.pipe.base.ExecutionResources`, optional 

86 The resources available to this quantum when executing. 

87 skipExisting : `bool`, optional 

88 If `True`, skip quanta whose metadata datasets are already stored. 

89 Unlike ``skipExistingIn``, this works with limited butlers as well as 

90 full butlers. Always set to `True` if ``skipExistingIn`` matches 

91 ``butler.run``. 

92 assumeNoExistingOutputs : `bool`, optional 

93 If `True`, assume preexisting outputs are impossible (e.g. because this 

94 is known by higher-level code to be a new ``RUN`` collection), and do 

95 not look for them. This causes the ``skipExisting`` and 

96 ``clobberOutputs`` options to be ignored, but unlike just setting both 

97 of those to `False`, it also avoids all dataset existence checks. 

98 raise_on_partial_outputs : `bool`, optional 

99 If `True` raise exceptions chained by 

100 `lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead of 

101 considering the partial result a success and continuing to run 

102 downstream tasks. 

103 job_metadata : `~collections.abc.Mapping` 

104 Mapping with extra metadata to embed within the quantum metadata under 

105 the "job" key. This is intended to correspond to information common 

106 to all quanta being executed in a single process, such as the time 

107 taken to load the quantum graph in a BPS job. 

108 """ 

109 

110 def __init__( 

111 self, 

112 butler: Butler | None, 

113 taskFactory: TaskFactory, 

114 skipExistingIn: Any = None, 

115 clobberOutputs: bool = False, 

116 enableLsstDebug: bool = False, 

117 limited_butler_factory: Callable[[Quantum], LimitedButler] | None = None, 

118 resources: ExecutionResources | None = None, 

119 skipExisting: bool = False, 

120 assumeNoExistingOutputs: bool = False, 

121 raise_on_partial_outputs: bool = True, 

122 job_metadata: Mapping[str, int | str | float] | None = None, 

123 ): 

124 super().__init__( 

125 butler=butler, 

126 task_factory=taskFactory, 

127 skip_existing_in=skipExistingIn, 

128 clobber_outputs=clobberOutputs, 

129 enable_lsst_debug=enableLsstDebug, 

130 limited_butler_factory=limited_butler_factory, 

131 resources=resources, 

132 skip_existing=skipExisting, 

133 assume_no_existing_outputs=assumeNoExistingOutputs, 

134 raise_on_partial_outputs=raise_on_partial_outputs, 

135 job_metadata=job_metadata, 

136 ) 

137 

138 def checkExistingOutputs( 

139 self, quantum: Quantum, task_node: TaskNode, /, limited_butler: LimitedButler 

140 ) -> bool: 

141 return super()._check_existing_outputs(quantum, task_node, limited_butler=limited_butler) 

142 

143 def updatedQuantumInputs( 

144 self, quantum: Quantum, task_node: TaskNode, /, limited_butler: LimitedButler 

145 ) -> Quantum: 

146 return super()._updated_quantum_inputs(quantum, task_node, limited_butler=limited_butler) 

147 

148 def runQuantum( 

149 self, 

150 task: PipelineTask, 

151 quantum: Quantum, 

152 task_node: TaskNode, 

153 /, 

154 limited_butler: LimitedButler, 

155 quantum_id: uuid.UUID | None = None, 

156 ) -> tuple[QuantumSuccessCaveats, list[uuid.UUID], ButlerMetrics]: 

157 return super()._run_quantum( 

158 task, quantum, task_node, limited_butler=limited_butler, quantum_id=quantum_id 

159 ) 

160 

161 def writeMetadata( 

162 self, quantum: Quantum, metadata: Any, task_node: TaskNode, /, limited_butler: LimitedButler 

163 ) -> None: 

164 return super()._write_metadata(quantum, metadata, task_node, limited_butler=limited_butler) 

165 

166 def initGlobals(self, quantum: Quantum) -> None: 

167 pass 

168 

169 @property 

170 def butler(self) -> Butler | None: 

171 return self._butler 

172 

173 @property 

174 def taskFactory(self) -> TaskFactory: 

175 return self._task_factory 

176 

177 @property 

178 def clobberOutputs(self) -> bool: 

179 return self._clobber_outputs 

180 

181 @property 

182 def enableLsstDebug(self) -> bool: 

183 return self._enable_lsst_debug 

184 

185 @property 

186 def limited_butler_factory(self) -> Callable[[Quantum], LimitedButler] | None: 

187 return self._limited_butler_factory 

188 

189 @property 

190 def resources(self) -> ExecutionResources | None: 

191 return self._resources 

192 

193 @property 

194 def assumeNoExistingOutputs(self) -> bool: 

195 return self._assume_no_existing_outputs 

196 

197 @property 

198 def raise_on_partial_outputs(self) -> bool: 

199 return self._raise_on_partial_outputs 

200 

201 @property 

202 def job_metadata(self) -> Mapping[str, int | str | float] | None: 

203 return self._job_metadata 

204 

205 @property 

206 def skipExisting(self) -> bool: 

207 return self._skip_existing