Coverage for tests/test_configOverrides.py: 17%
160 statements
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-23 10:31 +0000
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-23 10:31 +0000
1# This file is part of pipe_base.
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 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/>.
22"""Simple unit test for configOverrides.
23"""
25import tempfile
26import unittest
28import lsst.pex.config as pexConfig
29import lsst.utils.tests
30from lsst.pipe.base.configOverrides import ConfigOverrides
31from lsst.pipe.base.pipelineIR import ParametersIR
33# This is used in testSettingVar unit test
34TEST_CHOICE_VALUE = 1
37class ConfigTest(pexConfig.Config):
38 """Configuration used for testing."""
40 fStr = pexConfig.Field(dtype=str, default="default", doc="test")
41 fBool = pexConfig.Field(dtype=bool, default=False, doc="test")
42 fInt = pexConfig.Field(dtype=int, default=-1, doc="test")
43 fFloat = pexConfig.Field(dtype=float, default=-1.0, doc="test")
45 fListStr = pexConfig.ListField(dtype=str, default=[], doc="test")
46 fListBool = pexConfig.ListField(dtype=bool, default=[], doc="test")
47 fListInt = pexConfig.ListField(dtype=int, default=[], doc="test")
49 fChoiceStr = pexConfig.ChoiceField(dtype=str, allowed=dict(A="a", B="b", C="c"), doc="test")
50 fChoiceInt = pexConfig.ChoiceField(dtype=int, allowed={1: "a", 2: "b", 3: "c"}, doc="test")
52 fDictStrInt = pexConfig.DictField(keytype=str, itemtype=int, doc="test")
55class ConfigOverridesTestCase(unittest.TestCase):
56 """A test case for Task"""
58 def checkSingleFieldOverride(self, field, value, result=None):
59 """Apply overrides of a single field.
61 Parameters
62 ----------
63 field : `str`
64 Field name.
65 value :
66 Field value to set, can be a string or anything else.
67 result : optional
68 Expected value of the field.
69 """
70 config = ConfigTest()
71 overrides = ConfigOverrides()
72 overrides.addValueOverride(field, value)
73 overrides.applyTo(config)
74 self.assertEqual(getattr(config, field), result)
76 def testSimpleValueStr(self):
77 """Test for applying value override to a string field"""
78 field = "fStr"
80 # values of supported type
81 self.checkSingleFieldOverride(field, "string", "string")
83 # invalid input
84 with self.assertRaises(pexConfig.FieldValidationError):
85 self.checkSingleFieldOverride(field, 1)
87 def testSimpleValueBool(self):
88 """Test for applying value override to a boolean field"""
89 field = "fBool"
91 # values of supported type
92 self.checkSingleFieldOverride(field, True, True)
93 self.checkSingleFieldOverride(field, False, False)
95 # supported string conversions
96 self.checkSingleFieldOverride(field, "True", True)
97 self.checkSingleFieldOverride(field, "False", False)
99 # parseable but invalid input
100 with self.assertRaises(pexConfig.FieldValidationError):
101 self.checkSingleFieldOverride(field, 1)
102 with self.assertRaises(pexConfig.FieldValidationError):
103 self.checkSingleFieldOverride(field, [])
104 with self.assertRaises(pexConfig.FieldValidationError):
105 self.checkSingleFieldOverride(field, "1")
107 def testSimpleValueInt(self):
108 """Test for applying value override to a int field"""
109 field = "fInt"
111 # values of supported type
112 self.checkSingleFieldOverride(field, 0, 0)
113 self.checkSingleFieldOverride(field, 100, 100)
115 # supported string conversions
116 self.checkSingleFieldOverride(field, "0", 0)
117 self.checkSingleFieldOverride(field, "100", 100)
118 self.checkSingleFieldOverride(field, "-100", -100)
119 self.checkSingleFieldOverride(field, "0x100", 0x100)
121 # parseable but invalid input
122 with self.assertRaises(pexConfig.FieldValidationError):
123 self.checkSingleFieldOverride(field, 1.0)
124 with self.assertRaises(pexConfig.FieldValidationError):
125 self.checkSingleFieldOverride(field, "1.0")
126 with self.assertRaises(pexConfig.FieldValidationError):
127 self.checkSingleFieldOverride(field, "[]")
129 def testSimpleValueFloat(self):
130 """Test for applying value override to a float field"""
131 field = "fFloat"
133 # values of supported type
134 self.checkSingleFieldOverride(field, 0.0, 0.0)
135 self.checkSingleFieldOverride(field, 100.0, 100.0)
137 # supported string conversions
138 self.checkSingleFieldOverride(field, "0.", 0.0)
139 self.checkSingleFieldOverride(field, "100.0", 100.0)
140 self.checkSingleFieldOverride(field, "-1.2e10", -1.2e10)
142 # parseable but invalid input
143 with self.assertRaises(pexConfig.FieldValidationError):
144 self.checkSingleFieldOverride(field, [])
145 with self.assertRaises(pexConfig.FieldValidationError):
146 self.checkSingleFieldOverride(field, "(1, 1)")
148 def testListValueStr(self):
149 """Test for applying value override to a list field"""
150 field = "fListStr"
152 # values of supported type
153 self.checkSingleFieldOverride(field, ["a", "b"], ["a", "b"])
154 self.checkSingleFieldOverride(field, ("a", "b"), ["a", "b"])
156 # supported string conversions
157 self.checkSingleFieldOverride(field, '["a", "b"]', ["a", "b"])
158 self.checkSingleFieldOverride(field, '("a", "b")', ["a", "b"])
160 # parseable but invalid input
161 with self.assertRaises(pexConfig.FieldValidationError):
162 self.checkSingleFieldOverride(field, "['a', []]")
164 def testListValueBool(self):
165 """Test for applying value override to a list field"""
166 field = "fListBool"
168 # values of supported type
169 self.checkSingleFieldOverride(field, [True, False], [True, False])
170 self.checkSingleFieldOverride(field, (True, False), [True, False])
172 # supported string conversions
173 self.checkSingleFieldOverride(field, "[True, False]", [True, False])
174 self.checkSingleFieldOverride(field, "(True, False)", [True, False])
175 self.checkSingleFieldOverride(field, "['True', 'False']", [True, False])
177 with self.assertRaises(pexConfig.FieldValidationError):
178 self.checkSingleFieldOverride(field, "[1, 2]")
179 with self.assertRaises(pexConfig.FieldValidationError):
180 self.checkSingleFieldOverride(field, [0, 1])
181 with self.assertRaises(pexConfig.FieldValidationError):
182 self.checkSingleFieldOverride(field, "5")
184 def testListValueInt(self):
185 """Test for applying value override to a list field"""
186 field = "fListInt"
188 # values of supported type
189 self.checkSingleFieldOverride(field, [1, 2], [1, 2])
190 self.checkSingleFieldOverride(field, (1, 2), [1, 2])
192 # supported string conversions
193 self.checkSingleFieldOverride(field, "[1, 2]", [1, 2])
194 self.checkSingleFieldOverride(field, "(1, 2)", [1, 2])
195 self.checkSingleFieldOverride(field, "['1', '2']", [1, 2])
197 # parseable but invalid input
198 with self.assertRaises(pexConfig.FieldValidationError):
199 self.checkSingleFieldOverride(field, "[1.0, []]")
200 with self.assertRaises(pexConfig.FieldValidationError):
201 self.checkSingleFieldOverride(field, [[], []])
202 with self.assertRaises(pexConfig.FieldValidationError):
203 self.checkSingleFieldOverride(field, "5")
205 def testChoiceValueStr(self):
206 """Test for applying value override to a choice field"""
207 field = "fChoiceStr"
209 # values of supported type
210 self.checkSingleFieldOverride(field, "A", "A")
211 self.checkSingleFieldOverride(field, "B", "B")
213 # non-allowed value
214 with self.assertRaises(pexConfig.FieldValidationError):
215 self.checkSingleFieldOverride(field, "X")
217 def testChoiceValueInt(self):
218 """Test for applying value override to a choice field"""
219 field = "fChoiceInt"
221 # values of supported type
222 self.checkSingleFieldOverride(field, 1, 1)
223 self.checkSingleFieldOverride(field, 3, 3)
225 # supported string conversions
226 self.checkSingleFieldOverride(field, "1", 1)
228 # parseable but invalid input
229 with self.assertRaises(pexConfig.FieldValidationError):
230 self.checkSingleFieldOverride(field, "0")
231 with self.assertRaises(pexConfig.FieldValidationError):
232 self.checkSingleFieldOverride(field, "[1]")
233 with self.assertRaises(pexConfig.FieldValidationError):
234 self.checkSingleFieldOverride(field, [0, 1])
236 def testSettingVar(self):
237 """Test setting a field with a string that represents a variable."""
238 field = "fChoiceInt"
240 # verify loading variable
241 self.checkSingleFieldOverride(field, "TEST_CHOICE_VALUE", 1)
243 # Verify That python importing a variable works
244 config = ConfigTest()
245 overrides = ConfigOverrides()
246 overrides.addPythonOverride("from math import pi")
247 overrides.addValueOverride("fFloat", "pi")
248 overrides.applyTo(config)
249 from math import pi
251 self.assertEqual(config.fFloat, pi)
253 def testDictValueInt(self):
254 """Test for applying value override to a dict field"""
255 field = "fDictStrInt"
257 # values of supported type
258 self.checkSingleFieldOverride(field, dict(a=1, b=2), dict(a=1, b=2))
260 # supported string conversions
261 self.checkSingleFieldOverride(field, "{'a': 1, 'b': 2}", dict(a=1, b=2))
263 # parseable but invalid input
264 with self.assertRaises(pexConfig.FieldValidationError):
265 self.checkSingleFieldOverride(field, "{1: 2}")
266 with self.assertRaises(pexConfig.FieldValidationError):
267 self.checkSingleFieldOverride(field, "{'a': 'b'}")
268 with self.assertRaises(pexConfig.FieldValidationError):
269 self.checkSingleFieldOverride(field, {"a": "b"})
271 def testConfigParameters(self):
272 """Test that passing parameters works"""
273 config = ConfigTest()
274 parameters = ParametersIR(mapping={"number": 6, "text": "hello world"})
275 overrides = ConfigOverrides()
276 overrides.addParameters(parameters)
277 overrides.addPythonOverride("config.fStr = parameters.text")
278 with tempfile.NamedTemporaryFile(mode="w") as fileOverride:
279 fileOverride.write("config.fInt = parameters.number")
280 fileOverride.seek(0)
281 overrides.addFileOverride(fileOverride.name)
282 overrides.applyTo(config)
283 self.assertEqual(config.fStr, parameters.mapping["text"])
284 self.assertEqual(config.fInt, parameters.mapping["number"])
286 overrides = ConfigOverrides()
287 overrides.addParameters(parameters)
288 overrides.addPythonOverride("parameters.fail = 9")
289 with self.assertRaises(ValueError):
290 overrides.applyTo(config)
293class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase):
294 """Check for memory leaks."""
297def setup_module(module):
298 """Configure pytest."""
299 lsst.utils.tests.init()
302if __name__ == "__main__":
303 lsst.utils.tests.init()
304 unittest.main()