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 

22from collections import Counter, namedtuple 

23from glob import glob 

24import os 

25import re 

26import unittest 

27 

28from lsst.daf.butler.core.utils import findFileResources, getFullTypeName, globToRegex, iterable, Singleton 

29from lsst.daf.butler import Formatter, Registry 

30from lsst.daf.butler import NamedKeyDict, NamedValueSet, StorageClass 

31from lsst.daf.butler.core.utils import isplit 

32 

33TESTDIR = os.path.dirname(__file__) 

34 

35 

36class IterableTestCase(unittest.TestCase): 

37 """Tests for `iterable` helper. 

38 """ 

39 

40 def testNonIterable(self): 

41 self.assertEqual(list(iterable(0)), [0, ]) 

42 

43 def testString(self): 

44 self.assertEqual(list(iterable("hello")), ["hello", ]) 

45 

46 def testIterableNoString(self): 

47 self.assertEqual(list(iterable([0, 1, 2])), [0, 1, 2]) 

48 self.assertEqual(list(iterable(["hello", "world"])), ["hello", "world"]) 

49 

50 

51class SingletonTestCase(unittest.TestCase): 

52 """Tests of the Singleton metaclass""" 

53 

54 class IsSingleton(metaclass=Singleton): 

55 def __init__(self): 

56 self.data = {} 

57 self.id = 0 

58 

59 class IsBadSingleton(IsSingleton): 

60 def __init__(self, arg): 

61 """A singleton can not accept any arguments.""" 

62 self.arg = arg 

63 

64 class IsSingletonSubclass(IsSingleton): 

65 def __init__(self): 

66 super().__init__() 

67 

68 def testSingleton(self): 

69 one = SingletonTestCase.IsSingleton() 

70 two = SingletonTestCase.IsSingleton() 

71 

72 # Now update the first one and check the second 

73 one.data["test"] = 52 

74 self.assertEqual(one.data, two.data) 

75 two.id += 1 

76 self.assertEqual(one.id, two.id) 

77 

78 three = SingletonTestCase.IsSingletonSubclass() 

79 self.assertNotEqual(one.id, three.id) 

80 

81 with self.assertRaises(TypeError): 

82 SingletonTestCase.IsBadSingleton(52) 

83 

84 

85class NamedKeyDictTest(unittest.TestCase): 

86 

87 def setUp(self): 

88 self.TestTuple = namedtuple("TestTuple", ("name", "id")) 

89 self.a = self.TestTuple(name="a", id=1) 

90 self.b = self.TestTuple(name="b", id=2) 

91 self.dictionary = {self.a: 10, self.b: 20} 

92 self.names = {self.a.name, self.b.name} 

93 

94 def check(self, nkd): 

95 self.assertEqual(len(nkd), 2) 

96 self.assertEqual(nkd.names, self.names) 

97 self.assertEqual(nkd.keys(), self.dictionary.keys()) 

98 self.assertEqual(list(nkd.values()), list(self.dictionary.values())) 

99 self.assertEqual(list(nkd.items()), list(self.dictionary.items())) 

100 self.assertEqual(list(nkd.byName().values()), list(self.dictionary.values())) 

101 self.assertEqual(list(nkd.byName().keys()), list(nkd.names)) 

102 

103 def testConstruction(self): 

104 self.check(NamedKeyDict(self.dictionary)) 

105 self.check(NamedKeyDict(iter(self.dictionary.items()))) 

106 

107 def testDuplicateNameConstruction(self): 

108 self.dictionary[self.TestTuple(name="a", id=3)] = 30 

109 with self.assertRaises(AssertionError): 

110 NamedKeyDict(self.dictionary) 

111 with self.assertRaises(AssertionError): 

112 NamedKeyDict(iter(self.dictionary.items())) 

113 

114 def testNoNameConstruction(self): 

115 self.dictionary["a"] = 30 

116 with self.assertRaises(AttributeError): 

117 NamedKeyDict(self.dictionary) 

118 with self.assertRaises(AttributeError): 

119 NamedKeyDict(iter(self.dictionary.items())) 

120 

121 def testGetItem(self): 

122 nkd = NamedKeyDict(self.dictionary) 

123 self.assertEqual(nkd["a"], 10) 

124 self.assertEqual(nkd[self.a], 10) 

125 self.assertEqual(nkd["b"], 20) 

126 self.assertEqual(nkd[self.b], 20) 

127 self.assertIn("a", nkd) 

128 self.assertIn(self.b, nkd) 

129 

130 def testSetItem(self): 

131 nkd = NamedKeyDict(self.dictionary) 

132 nkd[self.a] = 30 

133 self.assertEqual(nkd["a"], 30) 

134 nkd["b"] = 40 

135 self.assertEqual(nkd[self.b], 40) 

136 with self.assertRaises(KeyError): 

137 nkd["c"] = 50 

138 with self.assertRaises(AssertionError): 

139 nkd[self.TestTuple("a", 3)] = 60 

140 

141 def testDelItem(self): 

142 nkd = NamedKeyDict(self.dictionary) 

143 del nkd[self.a] 

144 self.assertNotIn("a", nkd) 

145 del nkd["b"] 

146 self.assertNotIn(self.b, nkd) 

147 self.assertEqual(len(nkd), 0) 

148 

149 def testIter(self): 

150 self.assertEqual(set(iter(NamedKeyDict(self.dictionary))), set(self.dictionary)) 

151 

152 def testEquality(self): 

153 nkd = NamedKeyDict(self.dictionary) 

154 self.assertEqual(nkd, self.dictionary) 

155 self.assertEqual(self.dictionary, nkd) 

156 

157 

158class NamedValueSetTest(unittest.TestCase): 

159 

160 def setUp(self): 

161 self.TestTuple = namedtuple("TestTuple", ("name", "id")) 

162 self.a = self.TestTuple(name="a", id=1) 

163 self.b = self.TestTuple(name="b", id=2) 

164 self.c = self.TestTuple(name="c", id=3) 

165 

166 def testConstruction(self): 

167 for arg in ({self.a, self.b}, (self.a, self.b)): 

168 for nvs in (NamedValueSet(arg), NamedValueSet(arg).freeze()): 

169 self.assertEqual(len(nvs), 2) 

170 self.assertEqual(nvs.names, {"a", "b"}) 

171 self.assertCountEqual(nvs, {self.a, self.b}) 

172 self.assertCountEqual(nvs.asMapping().items(), [(self.a.name, self.a), (self.b.name, self.b)]) 

173 

174 def testNoNameConstruction(self): 

175 with self.assertRaises(AttributeError): 

176 NamedValueSet([self.a, "a"]) 

177 

178 def testGetItem(self): 

179 nvs = NamedValueSet({self.a, self.b, self.c}) 

180 self.assertEqual(nvs["a"], self.a) 

181 self.assertEqual(nvs[self.a], self.a) 

182 self.assertEqual(nvs["b"], self.b) 

183 self.assertEqual(nvs[self.b], self.b) 

184 self.assertIn("a", nvs) 

185 self.assertIn(self.b, nvs) 

186 

187 def testEquality(self): 

188 s = {self.a, self.b, self.c} 

189 nvs = NamedValueSet(s) 

190 self.assertEqual(nvs, s) 

191 self.assertEqual(s, nvs) 

192 

193 def checkOperator(self, result, expected): 

194 self.assertIsInstance(result, NamedValueSet) 

195 self.assertEqual(result, expected) 

196 

197 def testOperators(self): 

198 ab = NamedValueSet({self.a, self.b}) 

199 bc = NamedValueSet({self.b, self.c}) 

200 self.checkOperator(ab & bc, {self.b}) 

201 self.checkOperator(ab | bc, {self.a, self.b, self.c}) 

202 self.checkOperator(ab ^ bc, {self.a, self.c}) 

203 self.checkOperator(ab - bc, {self.a}) 

204 

205 

206class TestButlerUtils(unittest.TestCase): 

207 """Tests of the simple utilities.""" 

208 

209 def testTypeNames(self): 

210 # Check types and also an object 

211 tests = [(Formatter, "lsst.daf.butler.core.formatter.Formatter"), 

212 (int, "int"), 

213 (StorageClass, "lsst.daf.butler.core.storageClass.StorageClass"), 

214 (StorageClass(None), "lsst.daf.butler.core.storageClass.StorageClass"), 

215 (Registry, "lsst.daf.butler.registry.Registry")] 

216 

217 for item, typeName in tests: 

218 self.assertEqual(getFullTypeName(item), typeName) 

219 

220 def testIsplit(self): 

221 # Test compatibility with str.split 

222 seps = ("\n", " ", "d") 

223 input_str = "ab\ncd ef\n" 

224 

225 for sep in seps: 

226 for input in (input_str, input_str.encode()): 

227 test_sep = sep.encode() if isinstance(input, bytes) else sep 

228 isp = list(isplit(input, sep=test_sep)) 

229 ssp = input.split(test_sep) 

230 self.assertEqual(isp, ssp) 

231 

232 

233class FindFileResourcesTestCase(unittest.TestCase): 

234 

235 def test_getSingleFile(self): 

236 """Test getting a file by its file name.""" 

237 filename = os.path.join(TESTDIR, "config/basic/butler.yaml") 

238 self.assertEqual([filename], findFileResources([filename])) 

239 

240 def test_getAllFiles(self): 

241 """Test getting all the files by not passing a regex.""" 

242 expected = Counter([p for p in glob(os.path.join(TESTDIR, "config", "**"), recursive=True) 

243 if os.path.isfile(p)]) 

244 self.assertNotEqual(len(expected), 0) # verify some files were found 

245 files = Counter(findFileResources([os.path.join(TESTDIR, "config")])) 

246 self.assertEqual(expected, files) 

247 

248 def test_getAllFilesRegex(self): 

249 """Test getting all the files with a regex-specified file ending.""" 

250 expected = Counter(glob(os.path.join(TESTDIR, "config", "**", "*.yaml"), recursive=True)) 

251 self.assertNotEqual(len(expected), 0) # verify some files were found 

252 files = Counter(findFileResources([os.path.join(TESTDIR, "config")], r"\.yaml\b")) 

253 self.assertEqual(expected, files) 

254 

255 def test_multipleInputs(self): 

256 """Test specifying more than one location to find a files.""" 

257 expected = Counter(glob(os.path.join(TESTDIR, "config", "basic", "**", "*.yaml"), recursive=True)) 

258 expected.update(glob(os.path.join(TESTDIR, "config", "templates", "**", "*.yaml"), recursive=True)) 

259 self.assertNotEqual(len(expected), 0) # verify some files were found 

260 files = Counter(findFileResources([os.path.join(TESTDIR, "config", "basic"), 

261 os.path.join(TESTDIR, "config", "templates")], 

262 r"\.yaml\b")) 

263 self.assertEqual(expected, files) 

264 

265 

266class GlobToRegexTestCase(unittest.TestCase): 

267 

268 def testStarInList(self): 

269 """Test that if a one of the items in the expression list is a star 

270 (stand-alone) then ``...`` is returned (which implies no restrictions) 

271 """ 

272 self.assertIs(globToRegex(["foo", "*", "bar"]), ...) 

273 

274 def testGlobList(self): 

275 """Test that a list of glob strings converts as expected to a regex and 

276 returns in the expected list. 

277 """ 

278 # test an absolute string 

279 patterns = globToRegex(["bar"]) 

280 self.assertEqual(len(patterns), 1) 

281 self.assertTrue(bool(re.fullmatch(patterns[0], "bar"))) 

282 self.assertIsNone(re.fullmatch(patterns[0], "boz")) 

283 

284 # test leading & trailing wildcard in multiple patterns 

285 patterns = globToRegex(["ba*", "*.fits"]) 

286 self.assertEqual(len(patterns), 2) 

287 # check the "ba*" pattern: 

288 self.assertTrue(bool(re.fullmatch(patterns[0], "bar"))) 

289 self.assertTrue(bool(re.fullmatch(patterns[0], "baz"))) 

290 self.assertIsNone(re.fullmatch(patterns[0], "boz.fits")) 

291 # check the "*.fits" pattern: 

292 self.assertTrue(bool(re.fullmatch(patterns[1], "bar.fits"))) 

293 self.assertTrue(re.fullmatch(patterns[1], "boz.fits")) 

294 self.assertIsNone(re.fullmatch(patterns[1], "boz.hdf5")) 

295 

296 

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

298 unittest.main()