Coverage for tests/test_configOverrides.py: 17%
160 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-02 03:31 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-02 03:31 -0700
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 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/>.
28"""Simple unit test for configOverrides.
29"""
31import tempfile
32import unittest
34import lsst.pex.config as pexConfig
35import lsst.utils.tests
36from lsst.pipe.base.configOverrides import ConfigOverrides
37from lsst.pipe.base.pipelineIR import ParametersIR
39# This is used in testSettingVar unit test
40TEST_CHOICE_VALUE = 1
43class ConfigTest(pexConfig.Config):
44 """Configuration used for testing."""
46 fStr = pexConfig.Field(dtype=str, default="default", doc="test")
47 fBool = pexConfig.Field(dtype=bool, default=False, doc="test")
48 fInt = pexConfig.Field(dtype=int, default=-1, doc="test")
49 fFloat = pexConfig.Field(dtype=float, default=-1.0, doc="test")
51 fListStr = pexConfig.ListField(dtype=str, default=[], doc="test")
52 fListBool = pexConfig.ListField(dtype=bool, default=[], doc="test")
53 fListInt = pexConfig.ListField(dtype=int, default=[], doc="test")
55 fChoiceStr = pexConfig.ChoiceField(dtype=str, allowed=dict(A="a", B="b", C="c"), doc="test")
56 fChoiceInt = pexConfig.ChoiceField(dtype=int, allowed={1: "a", 2: "b", 3: "c"}, doc="test")
58 fDictStrInt = pexConfig.DictField(keytype=str, itemtype=int, doc="test")
61class ConfigOverridesTestCase(unittest.TestCase):
62 """A test case for Task."""
64 def checkSingleFieldOverride(self, field, value, result=None):
65 """Apply overrides of a single field.
67 Parameters
68 ----------
69 field : `str`
70 Field name.
71 value : `typing.Any`
72 Field value to set, can be a string or anything else.
73 result : optional
74 Expected value of the field.
75 """
76 config = ConfigTest()
77 overrides = ConfigOverrides()
78 overrides.addValueOverride(field, value)
79 overrides.applyTo(config)
80 self.assertEqual(getattr(config, field), result)
82 def testSimpleValueStr(self):
83 """Test for applying value override to a string field."""
84 field = "fStr"
86 # values of supported type
87 self.checkSingleFieldOverride(field, "string", "string")
89 # invalid input
90 with self.assertRaises(pexConfig.FieldValidationError):
91 self.checkSingleFieldOverride(field, 1)
93 def testSimpleValueBool(self):
94 """Test for applying value override to a boolean field."""
95 field = "fBool"
97 # values of supported type
98 self.checkSingleFieldOverride(field, True, True)
99 self.checkSingleFieldOverride(field, False, False)
101 # supported string conversions
102 self.checkSingleFieldOverride(field, "True", True)
103 self.checkSingleFieldOverride(field, "False", False)
105 # parseable but invalid input
106 with self.assertRaises(pexConfig.FieldValidationError):
107 self.checkSingleFieldOverride(field, 1)
108 with self.assertRaises(pexConfig.FieldValidationError):
109 self.checkSingleFieldOverride(field, [])
110 with self.assertRaises(pexConfig.FieldValidationError):
111 self.checkSingleFieldOverride(field, "1")
113 def testSimpleValueInt(self):
114 """Test for applying value override to a int field."""
115 field = "fInt"
117 # values of supported type
118 self.checkSingleFieldOverride(field, 0, 0)
119 self.checkSingleFieldOverride(field, 100, 100)
121 # supported string conversions
122 self.checkSingleFieldOverride(field, "0", 0)
123 self.checkSingleFieldOverride(field, "100", 100)
124 self.checkSingleFieldOverride(field, "-100", -100)
125 self.checkSingleFieldOverride(field, "0x100", 0x100)
127 # parseable but invalid input
128 with self.assertRaises(pexConfig.FieldValidationError):
129 self.checkSingleFieldOverride(field, 1.0)
130 with self.assertRaises(pexConfig.FieldValidationError):
131 self.checkSingleFieldOverride(field, "1.0")
132 with self.assertRaises(pexConfig.FieldValidationError):
133 self.checkSingleFieldOverride(field, "[]")
135 def testSimpleValueFloat(self):
136 """Test for applying value override to a float field."""
137 field = "fFloat"
139 # values of supported type
140 self.checkSingleFieldOverride(field, 0.0, 0.0)
141 self.checkSingleFieldOverride(field, 100.0, 100.0)
143 # supported string conversions
144 self.checkSingleFieldOverride(field, "0.", 0.0)
145 self.checkSingleFieldOverride(field, "100.0", 100.0)
146 self.checkSingleFieldOverride(field, "-1.2e10", -1.2e10)
148 # parseable but invalid input
149 with self.assertRaises(pexConfig.FieldValidationError):
150 self.checkSingleFieldOverride(field, [])
151 with self.assertRaises(pexConfig.FieldValidationError):
152 self.checkSingleFieldOverride(field, "(1, 1)")
154 def testListValueStr(self):
155 """Test for applying value override to a list field."""
156 field = "fListStr"
158 # values of supported type
159 self.checkSingleFieldOverride(field, ["a", "b"], ["a", "b"])
160 self.checkSingleFieldOverride(field, ("a", "b"), ["a", "b"])
162 # supported string conversions
163 self.checkSingleFieldOverride(field, '["a", "b"]', ["a", "b"])
164 self.checkSingleFieldOverride(field, '("a", "b")', ["a", "b"])
166 # parseable but invalid input
167 with self.assertRaises(pexConfig.FieldValidationError):
168 self.checkSingleFieldOverride(field, "['a', []]")
170 def testListValueBool(self):
171 """Test for applying value override to a list field."""
172 field = "fListBool"
174 # values of supported type
175 self.checkSingleFieldOverride(field, [True, False], [True, False])
176 self.checkSingleFieldOverride(field, (True, False), [True, False])
178 # supported string conversions
179 self.checkSingleFieldOverride(field, "[True, False]", [True, False])
180 self.checkSingleFieldOverride(field, "(True, False)", [True, False])
181 self.checkSingleFieldOverride(field, "['True', 'False']", [True, False])
183 with self.assertRaises(pexConfig.FieldValidationError):
184 self.checkSingleFieldOverride(field, "[1, 2]")
185 with self.assertRaises(pexConfig.FieldValidationError):
186 self.checkSingleFieldOverride(field, [0, 1])
187 with self.assertRaises(pexConfig.FieldValidationError):
188 self.checkSingleFieldOverride(field, "5")
190 def testListValueInt(self):
191 """Test for applying value override to a list field."""
192 field = "fListInt"
194 # values of supported type
195 self.checkSingleFieldOverride(field, [1, 2], [1, 2])
196 self.checkSingleFieldOverride(field, (1, 2), [1, 2])
198 # supported string conversions
199 self.checkSingleFieldOverride(field, "[1, 2]", [1, 2])
200 self.checkSingleFieldOverride(field, "(1, 2)", [1, 2])
201 self.checkSingleFieldOverride(field, "['1', '2']", [1, 2])
203 # parseable but invalid input
204 with self.assertRaises(pexConfig.FieldValidationError):
205 self.checkSingleFieldOverride(field, "[1.0, []]")
206 with self.assertRaises(pexConfig.FieldValidationError):
207 self.checkSingleFieldOverride(field, [[], []])
208 with self.assertRaises(pexConfig.FieldValidationError):
209 self.checkSingleFieldOverride(field, "5")
211 def testChoiceValueStr(self):
212 """Test for applying value override to a choice field."""
213 field = "fChoiceStr"
215 # values of supported type
216 self.checkSingleFieldOverride(field, "A", "A")
217 self.checkSingleFieldOverride(field, "B", "B")
219 # non-allowed value
220 with self.assertRaises(pexConfig.FieldValidationError):
221 self.checkSingleFieldOverride(field, "X")
223 def testChoiceValueInt(self):
224 """Test for applying value override to a choice field."""
225 field = "fChoiceInt"
227 # values of supported type
228 self.checkSingleFieldOverride(field, 1, 1)
229 self.checkSingleFieldOverride(field, 3, 3)
231 # supported string conversions
232 self.checkSingleFieldOverride(field, "1", 1)
234 # parseable but invalid input
235 with self.assertRaises(pexConfig.FieldValidationError):
236 self.checkSingleFieldOverride(field, "0")
237 with self.assertRaises(pexConfig.FieldValidationError):
238 self.checkSingleFieldOverride(field, "[1]")
239 with self.assertRaises(pexConfig.FieldValidationError):
240 self.checkSingleFieldOverride(field, [0, 1])
242 def testSettingVar(self):
243 """Test setting a field with a string that represents a variable."""
244 field = "fChoiceInt"
246 # verify loading variable
247 self.checkSingleFieldOverride(field, "TEST_CHOICE_VALUE", 1)
249 # Verify That python importing a variable works
250 config = ConfigTest()
251 overrides = ConfigOverrides()
252 overrides.addPythonOverride("from math import pi")
253 overrides.addValueOverride("fFloat", "pi")
254 overrides.applyTo(config)
255 from math import pi
257 self.assertEqual(config.fFloat, pi)
259 def testDictValueInt(self):
260 """Test for applying value override to a dict field."""
261 field = "fDictStrInt"
263 # values of supported type
264 self.checkSingleFieldOverride(field, dict(a=1, b=2), dict(a=1, b=2))
266 # supported string conversions
267 self.checkSingleFieldOverride(field, "{'a': 1, 'b': 2}", dict(a=1, b=2))
269 # parseable but invalid input
270 with self.assertRaises(pexConfig.FieldValidationError):
271 self.checkSingleFieldOverride(field, "{1: 2}")
272 with self.assertRaises(pexConfig.FieldValidationError):
273 self.checkSingleFieldOverride(field, "{'a': 'b'}")
274 with self.assertRaises(pexConfig.FieldValidationError):
275 self.checkSingleFieldOverride(field, {"a": "b"})
277 def testConfigParameters(self):
278 """Test that passing parameters works."""
279 config = ConfigTest()
280 parameters = ParametersIR(mapping={"number": 6, "text": "hello world"})
281 overrides = ConfigOverrides()
282 overrides.addParameters(parameters)
283 overrides.addPythonOverride("config.fStr = parameters.text")
284 with tempfile.NamedTemporaryFile(mode="w") as fileOverride:
285 fileOverride.write("config.fInt = parameters.number")
286 fileOverride.seek(0)
287 overrides.addFileOverride(fileOverride.name)
288 overrides.applyTo(config)
289 self.assertEqual(config.fStr, parameters.mapping["text"])
290 self.assertEqual(config.fInt, parameters.mapping["number"])
292 overrides = ConfigOverrides()
293 overrides.addParameters(parameters)
294 overrides.addPythonOverride("parameters.fail = 9")
295 with self.assertRaises(ValueError):
296 overrides.applyTo(config)
299class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase):
300 """Check for memory leaks."""
303def setup_module(module):
304 """Configure pytest."""
305 lsst.utils.tests.init()
308if __name__ == "__main__":
309 lsst.utils.tests.init()
310 unittest.main()