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 pipe_tasks. 

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 

22import unittest 

23from io import StringIO 

24 

25from lsst.pipe.tasks.configurableActions import (ConfigurableActionStructField, ConfigurableAction, 

26 ConfigurableActionField) 

27from lsst.pex.config import Config, Field, FieldValidationError 

28 

29 

30class TestAction1(ConfigurableAction): 

31 var = Field(doc="test field", dtype=int, default=0) 

32 

33 def __call__(self): 

34 return self.var 

35 

36 def validate(self): 

37 assert(self.var is not None) 

38 

39 

40class TestAction2(ConfigurableAction): 

41 var = Field(doc="test field", dtype=int, default=1) 

42 

43 def __call__(self): 

44 return self.var 

45 

46 def validate(self): 

47 assert(self.var is not None) 

48 

49 

50class TestAction3(ConfigurableAction): 

51 var = Field(doc="test field", dtype=int, default=3) 

52 

53 def __call__(self): 

54 return self.var 

55 

56 def validate(self): 

57 assert(self.var is not None) 

58 

59 

60class ConfigurableActionsTestCase(unittest.TestCase): 

61 def _createConfig(self, default=None, singleDefault=None): 

62 class TestConfig(Config): 

63 actions = ConfigurableActionStructField(doc="Actions to be tested", default=default) 

64 singleAction = ConfigurableActionField(doc="A configurable action", default=singleDefault) 

65 return TestConfig 

66 

67 def testConfigInstatiation(self): 

68 # This will raise if there is an issue instantiating something 

69 configClass = self._createConfig() 

70 config = configClass() 

71 self.assertTrue(hasattr(config, "actions")) 

72 self.assertTrue(hasattr(config, "singleAction")) 

73 

74 # test again with default values 

75 configClass = self._createConfig(default={"test1": TestAction1}, singleDefault=TestAction1) 

76 config = configClass() 

77 

78 # verify the defaults were created 

79 self.assertTrue(hasattr(config.actions, "test1")) 

80 self.assertTrue(hasattr(config.actions.test1, "var")) 

81 self.assertEqual(config.actions.test1.var, 0) 

82 

83 self.assertTrue(hasattr(config.singleAction, "var")) 

84 self.assertEqual(config.singleAction.var, 0) 

85 

86 def testAssignment(self): 

87 # Struct actions 

88 # Test that a new action can be added with assignment 

89 configClass = self._createConfig(default={"test1": TestAction1}) 

90 config = configClass() 

91 config.actions.test2 = TestAction2 

92 

93 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2")) 

94 self.assertEqual(config.actions.test2.var, 1) 

95 

96 # verify the same as above, but assigning with instances 

97 configClass = self._createConfig(default={"test1": TestAction1}) 

98 config = configClass() 

99 config.actions.test3 = TestAction3() 

100 

101 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test3")) 

102 self.assertEqual(config.actions.test3.var, 3) 

103 

104 # The following is designed to support pipeline config setting 

105 # Test assignment using the update accessor 

106 configClass = self._createConfig(default={"test1": TestAction1}) 

107 config = configClass() 

108 config.actions.update = {"test2": TestAction2, "test3": TestAction3} 

109 

110 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2", "test3")) 

111 

112 configClass = self._createConfig(default={"test1": TestAction1}) 

113 configClass2 = self._createConfig(default={"test2": TestAction2, "test3": TestAction3}) 

114 config = configClass() 

115 config2 = configClass2() 

116 config.actions.update = config2.actions 

117 

118 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2", "test3")) 

119 

120 # Test remove "assignment" using the remove accessor 

121 configClass = self._createConfig(default={"test1": TestAction1, "test2": TestAction2, 

122 "test3": TestAction3}) 

123 config = configClass() 

124 config.actions.remove = ("test1", "test2") 

125 self.assertEqual(tuple(config.actions.fieldNames), ("test3", )) 

126 

127 configClass = self._createConfig(default={"test1": TestAction1, "test2": TestAction2, 

128 "test3": TestAction3}) 

129 config = configClass() 

130 config.actions.remove = "test1" 

131 self.assertEqual(tuple(config.actions.fieldNames), ("test2", "test3")) 

132 

133 # singleAction 

134 # Test that an action can be reassigned 

135 configClass = self._createConfig(singleDefault=TestAction1) 

136 config = configClass() 

137 self.assertEqual(config.singleAction(), 0) 

138 

139 config.singleAction = TestAction2 

140 self.assertEqual(config.singleAction(), 1) 

141 

142 config.singleAction = TestAction3() 

143 self.assertEqual(config.singleAction(), 3) 

144 

145 def testValidate(self): 

146 configClass = self._createConfig(default={"test1": TestAction1, "test2": TestAction2, 

147 "test3": TestAction3}, singleDefault=TestAction1) 

148 config = configClass() 

149 config.validate() 

150 

151 def testFreeze(self): 

152 configClass = self._createConfig(default={"test1": TestAction1, "test2": TestAction2}, 

153 singleDefault=TestAction1) 

154 config = configClass() 

155 config.freeze() 

156 

157 with self.assertRaises(FieldValidationError): 

158 config.actions.test3 = TestAction3 

159 

160 with self.assertRaises(FieldValidationError): 

161 config.actions.test1.var = 2 

162 

163 with self.assertRaises(FieldValidationError): 

164 config.actions.test2.var = 0 

165 

166 with self.assertRaises(FieldValidationError): 

167 config.singleAction = TestAction2 

168 

169 with self.assertRaises(FieldValidationError): 

170 config.singleAction.var = 3 

171 

172 def testCompare(self): 

173 configClass = self._createConfig(default={"test1": TestAction1, "test2": TestAction2}, 

174 singleDefault=TestAction1) 

175 config = configClass() 

176 config2 = configClass() 

177 

178 self.assertTrue(config.compare(config2)) 

179 

180 # Test equality fail for ConfigurableActionsStructField 

181 config3 = configClass() 

182 config3.actions.test1.var = 99 

183 self.assertFalse(config.compare(config3)) 

184 

185 # Test equality fail for ConfigurableActionsField 

186 config4 = configClass() 

187 config4.singleAction.var = 99 

188 self.assertFalse(config.compare(config4)) 

189 

190 def testSave(self): 

191 # This method will also test rename, as it is part of the 

192 # implementation in pex_config 

193 ioObject = StringIO() 

194 configClass = self._createConfig(default={"test1": TestAction1}, 

195 singleDefault=TestAction1) 

196 config = configClass() 

197 

198 config.saveToStream(ioObject) 

199 loadedConfig = configClass() 

200 loadedConfig.loadFromStream(ioObject.read()) 

201 self.assertTrue(config.compare(loadedConfig)) 

202 # Be sure that the fields are actually there 

203 self.assertEqual(loadedConfig.actions.test1.var, 0) 

204 self.assertEqual(loadedConfig.singleAction.var, 0) 

205 

206 def testToDict(self): 

207 """Test the toDict interface""" 

208 configClass = self._createConfig(default={"test1": TestAction1}, 

209 singleDefault=TestAction1) 

210 config = configClass() 

211 self.assertEqual(config.toDict(), {'actions': {'test1': {'var': 0}}, 'singleAction': {'var': 0}}) 

212 

213 

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

215 unittest.main()