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

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

21 

22import os 

23import pickle 

24import unittest 

25 

26from lsst.daf.butler import StorageClass, StorageClassFactory, StorageClassConfig, StorageClassDelegate 

27 

28"""Tests related to the StorageClass infrastructure. 

29""" 

30 

31TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

32 

33 

34class PythonType: 

35 """A dummy class to test the registry of Python types.""" 

36 pass 

37 

38 

39class StorageClassFactoryTestCase(unittest.TestCase): 

40 """Tests of the storage class infrastructure. 

41 """ 

42 

43 def testCreation(self): 

44 """Test that we can dynamically create storage class subclasses. 

45 

46 This is critical for testing the factory functions.""" 

47 className = "TestImage" 

48 sc = StorageClass(className, pytype=dict) 

49 self.assertIsInstance(sc, StorageClass) 

50 self.assertEqual(sc.name, className) 

51 self.assertEqual(str(sc), className) 

52 self.assertFalse(sc.components) 

53 self.assertTrue(sc.validateInstance({})) 

54 self.assertFalse(sc.validateInstance("")) 

55 

56 r = repr(sc) 

57 self.assertIn("StorageClass", r) 

58 self.assertIn(className, r) 

59 self.assertNotIn("parameters", r) 

60 self.assertIn("pytype='dict'", r) 

61 

62 # Ensure we do not have a delegate 

63 with self.assertRaises(TypeError): 

64 sc.delegate() 

65 

66 # Allow no definition of python type 

67 scn = StorageClass(className) 

68 self.assertIs(scn.pytype, object) 

69 

70 # Include some components 

71 scc = StorageClass(className, pytype=PythonType, components={"comp1": sc, "comp2": sc}) 

72 self.assertIn("comp1", scc.components) 

73 r = repr(scc) 

74 self.assertIn("comp1", r) 

75 self.assertIn("lsst.daf.butler.core.storageClassDelegate.StorageClassDelegate", r) 

76 

77 # Ensure that we have a delegate 

78 self.assertIsInstance(scc.delegate(), StorageClassDelegate) 

79 

80 # Check we can create a storageClass using the name of an importable 

81 # type. 

82 sc2 = StorageClass("TestImage2", 

83 "lsst.daf.butler.core.storageClass.StorageClassFactory") 

84 self.assertIsInstance(sc2.pytype(), StorageClassFactory) 

85 self.assertIn("butler.core", repr(sc2)) 

86 

87 def testParameters(self): 

88 """Test that we can set parameters and validate them""" 

89 pt = ("a", "b") 

90 ps = {"a", "b"} 

91 pl = ["a", "b"] 

92 for p in (pt, ps, pl): 

93 sc1 = StorageClass("ParamClass", pytype=dict, parameters=p) 

94 self.assertEqual(sc1.parameters, ps) 

95 sc1.validateParameters(p) 

96 

97 sc1.validateParameters() 

98 sc1.validateParameters({"a": None, "b": None}) 

99 sc1.validateParameters(["a", ]) 

100 with self.assertRaises(KeyError): 

101 sc1.validateParameters({"a", "c"}) 

102 

103 def testEquality(self): 

104 """Test that StorageClass equality works""" 

105 className = "TestImage" 

106 sc1 = StorageClass(className, pytype=dict) 

107 sc2 = StorageClass(className, pytype=dict) 

108 self.assertEqual(sc1, sc2) 

109 sc3 = StorageClass(className + "2", pytype=str) 

110 self.assertNotEqual(sc1, sc3) 

111 

112 # Same StorageClass name but different python type 

113 sc4 = StorageClass(className, pytype=str) 

114 self.assertNotEqual(sc1, sc4) 

115 

116 # Parameters 

117 scp = StorageClass("Params", pytype=PythonType, parameters=["a", "b", "c"]) 

118 scp1 = StorageClass("Params", pytype=PythonType, parameters=["a", "b", "c"]) 

119 scp2 = StorageClass("Params", pytype=PythonType, parameters=["a", "b", "d", "e"]) 

120 self.assertEqual(scp, scp1) 

121 self.assertNotEqual(scp, scp2) 

122 

123 # Now with components 

124 sc5 = StorageClass("Composite", pytype=PythonType, 

125 components={"comp1": sc1, "comp2": sc3}) 

126 sc6 = StorageClass("Composite", pytype=PythonType, 

127 components={"comp1": sc1, "comp2": sc3}) 

128 self.assertEqual(sc5, sc6) 

129 self.assertNotEqual(sc5, sc3) 

130 sc7 = StorageClass("Composite", pytype=PythonType, 

131 components={"comp1": sc4, "comp2": sc3}) 

132 self.assertNotEqual(sc5, sc7) 

133 sc8 = StorageClass("Composite", pytype=PythonType, 

134 components={"comp2": sc3, "comp3": sc3}) 

135 self.assertNotEqual(sc5, sc8) 

136 sc9 = StorageClass("Composite", pytype=PythonType, 

137 components={"comp1": sc1, "comp2": sc3}, 

138 delegate="lsst.daf.butler.Butler") 

139 self.assertNotEqual(sc5, sc9) 

140 

141 def testRegistry(self): 

142 """Check that storage classes can be created on the fly and stored 

143 in a registry.""" 

144 className = "TestImage" 

145 factory = StorageClassFactory() 

146 newclass = StorageClass(className, pytype=PythonType) 

147 factory.registerStorageClass(newclass) 

148 sc = factory.getStorageClass(className) 

149 self.assertIsInstance(sc, StorageClass) 

150 self.assertEqual(sc.name, className) 

151 self.assertFalse(sc.components) 

152 self.assertEqual(sc.pytype, PythonType) 

153 self.assertIn(sc, factory) 

154 newclass2 = StorageClass("Temporary2", pytype=str) 

155 self.assertNotIn(newclass2, factory) 

156 factory.registerStorageClass(newclass2) 

157 self.assertIn(newclass2, factory) 

158 self.assertIn("Temporary2", factory) 

159 self.assertNotIn("Temporary3", factory) 

160 self.assertNotIn({}, factory) 

161 

162 # Make sure we can't register a storage class with the same name 

163 # but different values 

164 newclass3 = StorageClass("Temporary2", pytype=dict) 

165 with self.assertRaises(ValueError): 

166 factory.registerStorageClass(newclass3) 

167 

168 factory._unregisterStorageClass(newclass3.name) 

169 self.assertNotIn(newclass3, factory) 

170 self.assertNotIn(newclass3.name, factory) 

171 factory.registerStorageClass(newclass3) 

172 self.assertIn(newclass3, factory) 

173 self.assertIn(newclass3.name, factory) 

174 

175 # Check you can silently insert something that is already there 

176 factory.registerStorageClass(newclass3) 

177 

178 def testFactoryConfig(self): 

179 factory = StorageClassFactory() 

180 factory.addFromConfig(StorageClassConfig()) 

181 image = factory.getStorageClass("Image") 

182 imageF = factory.getStorageClass("ImageF") 

183 self.assertIsInstance(imageF, type(image)) 

184 self.assertNotEqual(imageF, image) 

185 

186 # Check component inheritance 

187 exposure = factory.getStorageClass("Exposure") 

188 exposureF = factory.getStorageClass("ExposureF") 

189 self.assertIsInstance(exposureF, type(exposure)) 

190 self.assertIsInstance(exposure.components["image"], type(image)) 

191 self.assertNotIsInstance(exposure.components["image"], type(imageF)) 

192 self.assertIsInstance(exposureF.components["image"], type(image)) 

193 self.assertIsInstance(exposureF.components["image"], type(imageF)) 

194 self.assertIn("wcs", exposure.components) 

195 self.assertIn("wcs", exposureF.components) 

196 

197 # Check parameters 

198 factory.addFromConfig(os.path.join(TESTDIR, "config", "basic", "storageClasses.yaml")) 

199 thing1 = factory.getStorageClass("ThingOne") 

200 thing2 = factory.getStorageClass("ThingTwo") 

201 self.assertIsInstance(thing2, type(thing1)) 

202 param1 = thing1.parameters 

203 param2 = thing2.parameters 

204 self.assertIn("param3", thing2.parameters) 

205 self.assertNotIn("param3", thing1.parameters) 

206 param2.remove("param3") 

207 self.assertEqual(param1, param2) 

208 

209 # Check that we can't have a new StorageClass that does not 

210 # inherit from StorageClass 

211 with self.assertRaises(ValueError): 

212 factory.makeNewStorageClass("ClassName", baseClass=StorageClassFactory) 

213 

214 sc = factory.makeNewStorageClass("ClassName") 

215 self.assertIsInstance(sc(), StorageClass) 

216 

217 def testPickle(self): 

218 """Test that we can pickle storageclasses. 

219 """ 

220 className = "TestImage" 

221 sc = StorageClass(className, pytype=dict) 

222 self.assertIsInstance(sc, StorageClass) 

223 self.assertEqual(sc.name, className) 

224 self.assertFalse(sc.components) 

225 sc2 = pickle.loads(pickle.dumps(sc)) 

226 self.assertEqual(sc2, sc) 

227 

228 

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

230 unittest.main()