Coverage for tests/test_dictField.py: 17%

104 statements  

« prev     ^ index     » next       coverage.py v7.4.2, created at 2024-02-23 11:29 +0000

1# This file is part of pex_config. 

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

27 

28import pickle 

29import unittest 

30 

31import lsst.pex.config as pexConfig 

32 

33 

34class Config1(pexConfig.Config): 

35 """First test config.""" 

36 

37 d1 = pexConfig.DictField("d1", keytype=str, itemtype=int, default={"hi": 4}, itemCheck=lambda x: x > 0) 37 ↛ exitline 37 didn't run the lambda on line 37

38 d2 = pexConfig.DictField("d2", keytype=str, itemtype=str, default=None) 

39 d3 = pexConfig.DictField("d3", keytype=float, itemtype=float, optional=True, itemCheck=lambda x: x > 0) 39 ↛ exitline 39 didn't run the lambda on line 39

40 d4 = pexConfig.DictField("d4", keytype=str, itemtype=None, default={}) 

41 

42 

43class DictFieldTest(unittest.TestCase): 

44 """Test DictField.""" 

45 

46 def testConstructor(self): 

47 try: 

48 

49 class BadKeytype(pexConfig.Config): 

50 d = pexConfig.DictField("...", keytype=list, itemtype=int) 

51 

52 except Exception: 

53 pass 

54 else: 

55 raise SyntaxError("Unsupported keyptype DictFields should not be allowed") 

56 

57 try: 

58 

59 class BadItemtype(pexConfig.Config): 

60 d = pexConfig.DictField("...", keytype=int, itemtype=dict) 

61 

62 except Exception: 

63 pass 

64 else: 

65 raise SyntaxError("Unsupported itemtype DictFields should not be allowed") 

66 

67 try: 

68 

69 class BadItemCheck(pexConfig.Config): 

70 d = pexConfig.DictField("...", keytype=int, itemtype=int, itemCheck=4) 

71 

72 except Exception: 

73 pass 

74 else: 

75 raise SyntaxError("Non-callable itemCheck DictFields should not be allowed") 

76 

77 try: 

78 

79 class BadDictCheck(pexConfig.Config): 

80 d = pexConfig.DictField("...", keytype=int, itemtype=int, dictCheck=4) 

81 

82 except Exception: 

83 pass 

84 else: 

85 raise SyntaxError("Non-callable dictCheck DictFields should not be allowed") 

86 

87 def testFieldTypeAnnotationRuntime(self): 

88 # test parsing type annotation for runtime keytype, itemtype 

89 testField = pexConfig.DictField[str, int](doc="test") 

90 self.assertEqual(testField.keytype, str) 

91 self.assertEqual(testField.itemtype, int) 

92 

93 # verify that forward references work correctly 

94 testField = pexConfig.DictField["float", "int"](doc="test") 

95 self.assertEqual(testField.keytype, float) 

96 self.assertEqual(testField.itemtype, int) 

97 

98 # verify that Field rejects single types 

99 with self.assertRaises(ValueError): 

100 pexConfig.DictField[int](doc="test") # type: ignore 

101 

102 # verify that Field raises in conflict with keytype, itemtype 

103 with self.assertRaises(ValueError): 

104 pexConfig.DictField[str, int](doc="test", keytype=int) 

105 

106 with self.assertRaises(ValueError): 

107 pexConfig.DictField[str, int](doc="test", itemtype=str) 

108 

109 # verify that Field does not raise if dtype agrees 

110 testField = pexConfig.DictField[int, str](doc="test", keytype=int, itemtype=str) 

111 self.assertEqual(testField.keytype, int) 

112 self.assertEqual(testField.itemtype, str) 

113 

114 def testAssignment(self): 

115 c = Config1() 

116 self.assertRaises(pexConfig.FieldValidationError, setattr, c, "d1", {3: 3}) 

117 self.assertRaises(pexConfig.FieldValidationError, setattr, c, "d1", {"a": 0}) 

118 self.assertRaises(pexConfig.FieldValidationError, setattr, c, "d1", [1.2, 3, 4]) 

119 c.d1 = None 

120 c.d1 = {"a": 1, "b": 2} 

121 self.assertRaises(pexConfig.FieldValidationError, setattr, c, "d3", {"hi": True}) 

122 c.d3 = {4: 5} 

123 self.assertEqual(c.d3, {4.0: 5.0}) 

124 d = {"a": None, "b": 4, "c": "foo"} 

125 c.d4 = d 

126 self.assertEqual(c.d4, d) 

127 c.d4["a"] = 12 

128 c.d4["b"] = "three" 

129 c.d4["c"] = None 

130 self.assertEqual(c.d4["a"], 12) 

131 self.assertEqual(c.d4["b"], "three") 

132 self.assertIsNone(c.d4["c"]) 

133 self.assertRaises(pexConfig.FieldValidationError, setattr, c, "d4", {"hi": [1, 2, 3]}) 

134 

135 def testValidate(self): 

136 c = Config1() 

137 self.assertRaises(pexConfig.FieldValidationError, Config1.validate, c) 

138 

139 c.d2 = {"a": "b"} 

140 c.validate() 

141 

142 def testInPlaceModification(self): 

143 c = Config1() 

144 self.assertRaises(pexConfig.FieldValidationError, c.d1.__setitem__, 2, 0) 

145 self.assertRaises(pexConfig.FieldValidationError, c.d1.__setitem__, "hi", 0) 

146 c.d1["hi"] = 10 

147 self.assertEqual(c.d1, {"hi": 10}) 

148 

149 c.d3 = {} 

150 c.d3[4] = 5 

151 self.assertEqual(c.d3, {4.0: 5.0}) 

152 

153 def testNoArbitraryAttributes(self): 

154 c = Config1() 

155 self.assertRaises(pexConfig.FieldValidationError, setattr, c.d1, "should", "fail") 

156 

157 def testEquality(self): 

158 """Test DictField.__eq__. 

159 

160 We create two dicts, with the keys explicitly added in a different 

161 order and test their equality. 

162 """ 

163 keys1 = ["A", "B", "C"] 

164 keys2 = ["X", "Y", "Z", "a", "b", "c", "d", "e"] 

165 

166 c1 = Config1() 

167 c1.d4 = {k: "" for k in keys1} 

168 for k in keys2: 

169 c1.d4[k] = "" 

170 

171 c2 = Config1() 

172 for k in keys2 + keys1: 

173 c2.d4[k] = "" 

174 

175 self.assertTrue(pexConfig.compareConfigs("test", c1, c2)) 

176 

177 def testNoPickle(self): 

178 """Test that pickle support is disabled for the proxy container.""" 

179 c = Config1() 

180 with self.assertRaises(pexConfig.UnexpectedProxyUsageError): 

181 pickle.dumps(c.d4) 

182 

183 

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

185 unittest.main()