Hide keyboard shortcuts

Hot-keys 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

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 <https://www.gnu.org/licenses/>. 

21 

22"""Simple unit test for Pipeline. 

23""" 

24 

25import io 

26import re 

27import unittest 

28 

29from lsst.pipe.base import (PipelineTask, PipelineTaskConfig, 

30 Pipeline, PipelineTaskConnections) 

31import lsst.pipe.base.connectionTypes as cT 

32from lsst.ctrl.mpexec.dotTools import pipeline2dot 

33import lsst.utils.tests 

34 

35 

36class ExamplePipelineTaskConnections(PipelineTaskConnections, dimensions=()): 

37 input1 = cT.Input(name="", 

38 dimensions=["visit", "detector"], 

39 storageClass="example", 

40 doc="Input for this task") 

41 input2 = cT.Input(name="", 

42 dimensions=["visit", "detector"], 

43 storageClass="example", 

44 doc="Input for this task") 

45 output1 = cT.Output(name="", 

46 dimensions=["visit", "detector"], 

47 storageClass="example", 

48 doc="Output for this task") 

49 output2 = cT.Output(name="", 

50 dimensions=["visit", "detector"], 

51 storageClass="example", 

52 doc="Output for this task") 

53 

54 def __init__(self, *, config=None): 

55 super().__init__(config=config) 

56 if not config.connections.input2: 

57 self.inputs.remove("input2") 

58 if not config.connections.output2: 

59 self.outputs.remove("output2") 

60 

61 

62class ExamplePipelineTaskConfig(PipelineTaskConfig, pipelineConnections=ExamplePipelineTaskConnections): 

63 pass 

64 

65 

66def _makeConfig(inputName, outputName, pipeline, label): 

67 """Factory method for config instances 

68 

69 inputName and outputName can be either string or tuple of strings 

70 with two items max. 

71 """ 

72 if isinstance(inputName, tuple): 

73 pipeline.addConfigOverride(label, "connections.input1", inputName[0]) 

74 pipeline.addConfigOverride(label, "connections.input2", inputName[1] if len(inputName) > 1 else "") 

75 else: 

76 pipeline.addConfigOverride(label, "connections.input1", inputName) 

77 

78 if isinstance(outputName, tuple): 

79 pipeline.addConfigOverride(label, "connections.output1", outputName[0]) 

80 pipeline.addConfigOverride(label, "connections.output2", outputName[1] if len(outputName) > 1 else "") 

81 else: 

82 pipeline.addConfigOverride(label, "connections.output1", outputName) 

83 

84 

85class ExamplePipelineTask(PipelineTask): 

86 ConfigClass = ExamplePipelineTaskConfig 

87 

88 

89def _makePipeline(tasks): 

90 """Generate Pipeline instance. 

91 

92 Parameters 

93 ---------- 

94 tasks : list of tuples 

95 Each tuple in the list has 3 or 4 items: 

96 - input DatasetType name(s), string or tuple of strings 

97 - output DatasetType name(s), string or tuple of strings 

98 - task label, string 

99 - optional task class object, can be None 

100 

101 Returns 

102 ------- 

103 Pipeline instance 

104 """ 

105 pipe = Pipeline("test pipeline") 

106 for task in tasks: 

107 inputs = task[0] 

108 outputs = task[1] 

109 label = task[2] 

110 klass = task[3] if len(task) > 3 else ExamplePipelineTask 

111 pipe.addTask(klass, label) 

112 _makeConfig(inputs, outputs, pipe, label) 

113 return list(pipe.toExpandedPipeline()) 

114 

115 

116class DotToolsTestCase(unittest.TestCase): 

117 """A test case for dotTools 

118 """ 

119 

120 def testPipeline2dot(self): 

121 """Tests for dotTools.pipeline2dot method 

122 """ 

123 pipeline = _makePipeline([("A", ("B", "C"), "task1"), 

124 ("C", "E", "task2"), 

125 ("B", "D", "task3"), 

126 (("D", "E"), "F", "task4")]) 

127 file = io.StringIO() 

128 pipeline2dot(pipeline, file) 

129 

130 # it's hard to validate complete output, just checking few basic things, 

131 # even that is not terribly stable 

132 lines = file.getvalue().strip().split('\n') 

133 ndatasets = 6 

134 ntasks = 4 

135 nedges = 10 

136 nextra = 2 # graph header and closing 

137 self.assertEqual(len(lines), ndatasets + ntasks + nedges + nextra) 

138 

139 # make sure that all node names are quoted 

140 nodeRe = re.compile(r"^([^ ]+) \[.+\];$") 

141 edgeRe = re.compile(r"^([^ ]+) *-> *([^ ]+);$") 

142 for line in lines: 

143 match = nodeRe.match(line) 

144 if match: 

145 node = match.group(1) 

146 self.assertEqual(node[0] + node[-1], '""') 

147 continue 

148 match = edgeRe.match(line) 

149 if match: 

150 for group in (1, 2): 

151 node = match.group(group) 

152 self.assertEqual(node[0] + node[-1], '""') 

153 continue 

154 

155 

156class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

157 pass 

158 

159 

160def setup_module(module): 

161 lsst.utils.tests.init() 

162 

163 

164if __name__ == "__main__": 164 ↛ 165line 164 didn't jump to line 165, because the condition on line 164 was never true

165 lsst.utils.tests.init() 

166 unittest.main()