Coverage for tests/test_configurableActions.py: 26%
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
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
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/>.
22import unittest
23from io import StringIO
25from lsst.pipe.tasks.configurableActions import (ConfigurableActionStructField, ConfigurableAction,
26 ConfigurableActionField)
27from lsst.pex.config import Config, Field, FieldValidationError
30class ActionTest1(ConfigurableAction):
31 var = Field(doc="test field", dtype=int, default=0)
33 def __call__(self):
34 return self.var
36 def validate(self):
37 assert(self.var is not None)
40class ActionTest2(ConfigurableAction):
41 var = Field(doc="test field", dtype=int, default=1)
43 def __call__(self):
44 return self.var
46 def validate(self):
47 assert(self.var is not None)
50class ActionTest3(ConfigurableAction):
51 var = Field(doc="test field", dtype=int, default=3)
53 def __call__(self):
54 return self.var
56 def validate(self):
57 assert(self.var is not None)
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
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"))
74 # test again with default values
75 configClass = self._createConfig(default={"test1": ActionTest1}, singleDefault=ActionTest1)
76 config = configClass()
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)
83 self.assertTrue(hasattr(config.singleAction, "var"))
84 self.assertEqual(config.singleAction.var, 0)
86 def testAssignment(self):
87 # Struct actions
88 # Test that a new action can be added with assignment
89 configClass = self._createConfig(default={"test1": ActionTest1})
90 config = configClass()
91 config.actions.test2 = ActionTest2
93 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2"))
94 self.assertEqual(config.actions.test2.var, 1)
96 # verify the same as above, but assigning with instances
97 configClass = self._createConfig(default={"test1": ActionTest1})
98 config = configClass()
99 config.actions.test3 = ActionTest3()
101 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test3"))
102 self.assertEqual(config.actions.test3.var, 3)
104 # The following is designed to support pipeline config setting
105 # Test assignment using the update accessor
106 configClass = self._createConfig(default={"test1": ActionTest1})
107 config = configClass()
108 config.actions.update = {"test2": ActionTest2, "test3": ActionTest3}
110 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2", "test3"))
112 configClass = self._createConfig(default={"test1": ActionTest1})
113 configClass2 = self._createConfig(default={"test2": ActionTest2, "test3": ActionTest3})
114 config = configClass()
115 config2 = configClass2()
116 config.actions.update = config2.actions
118 self.assertEqual(tuple(config.actions.fieldNames), ("test1", "test2", "test3"))
120 # Test remove "assignment" using the remove accessor
121 configClass = self._createConfig(default={"test1": ActionTest1, "test2": ActionTest2,
122 "test3": ActionTest3})
123 config = configClass()
124 config.actions.remove = ("test1", "test2")
125 self.assertEqual(tuple(config.actions.fieldNames), ("test3", ))
127 configClass = self._createConfig(default={"test1": ActionTest1, "test2": ActionTest2,
128 "test3": ActionTest3})
129 config = configClass()
130 config.actions.remove = "test1"
131 self.assertEqual(tuple(config.actions.fieldNames), ("test2", "test3"))
133 # singleAction
134 # Test that an action can be reassigned
135 configClass = self._createConfig(singleDefault=ActionTest1)
136 config = configClass()
137 self.assertEqual(config.singleAction(), 0)
139 config.singleAction = ActionTest2
140 self.assertEqual(config.singleAction(), 1)
142 config.singleAction = ActionTest3()
143 self.assertEqual(config.singleAction(), 3)
145 def testValidate(self):
146 configClass = self._createConfig(default={"test1": ActionTest1, "test2": ActionTest2,
147 "test3": ActionTest3}, singleDefault=ActionTest1)
148 config = configClass()
149 config.validate()
151 def testFreeze(self):
152 configClass = self._createConfig(default={"test1": ActionTest1, "test2": ActionTest2},
153 singleDefault=ActionTest1)
154 config = configClass()
155 config.freeze()
157 with self.assertRaises(FieldValidationError):
158 config.actions.test3 = ActionTest3
160 with self.assertRaises(FieldValidationError):
161 config.actions.test1.var = 2
163 with self.assertRaises(FieldValidationError):
164 config.actions.test2.var = 0
166 with self.assertRaises(FieldValidationError):
167 config.singleAction = ActionTest2
169 with self.assertRaises(FieldValidationError):
170 config.singleAction.var = 3
172 def testCompare(self):
173 configClass = self._createConfig(default={"test1": ActionTest1, "test2": ActionTest2},
174 singleDefault=ActionTest1)
175 config = configClass()
176 config2 = configClass()
178 self.assertTrue(config.compare(config2))
180 # Test equality fail for ConfigurableActionsStructField
181 config3 = configClass()
182 config3.actions.test1.var = 99
183 self.assertFalse(config.compare(config3))
185 # Test equality fail for ConfigurableActionsField
186 config4 = configClass()
187 config4.singleAction.var = 99
188 self.assertFalse(config.compare(config4))
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": ActionTest1},
195 singleDefault=ActionTest1)
196 config = configClass()
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)
206 def testToDict(self):
207 """Test the toDict interface"""
208 configClass = self._createConfig(default={"test1": ActionTest1},
209 singleDefault=ActionTest1)
210 config = configClass()
211 self.assertEqual(config.toDict(), {'actions': {'test1': {'var': 0}}, 'singleAction': {'var': 0}})
214if __name__ == "__main__": 214 ↛ 215line 214 didn't jump to line 215, because the condition on line 214 was never true
215 unittest.main()