Coverage for tests/test_utils.py: 19%

138 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-25 15:14 +0000

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 re 

24import unittest 

25from collections import namedtuple 

26 

27from lsst.daf.butler import NamedKeyDict, NamedValueSet 

28from lsst.daf.butler.core.utils import globToRegex 

29 

30TESTDIR = os.path.dirname(__file__) 

31 

32 

33class NamedKeyDictTest(unittest.TestCase): 

34 """Tests for NamedKeyDict.""" 

35 

36 def setUp(self): 

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

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

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

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

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

42 

43 def check(self, nkd): 

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

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

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

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

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

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

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

51 

52 def testConstruction(self): 

53 self.check(NamedKeyDict(self.dictionary)) 

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

55 

56 def testDuplicateNameConstruction(self): 

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

58 with self.assertRaises(AssertionError): 

59 NamedKeyDict(self.dictionary) 

60 with self.assertRaises(AssertionError): 

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

62 

63 def testNoNameConstruction(self): 

64 self.dictionary["a"] = 30 

65 with self.assertRaises(AttributeError): 

66 NamedKeyDict(self.dictionary) 

67 with self.assertRaises(AttributeError): 

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

69 

70 def testGetItem(self): 

71 nkd = NamedKeyDict(self.dictionary) 

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

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

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

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

76 self.assertIn("a", nkd) 

77 self.assertIn(self.b, nkd) 

78 

79 def testSetItem(self): 

80 nkd = NamedKeyDict(self.dictionary) 

81 nkd[self.a] = 30 

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

83 nkd["b"] = 40 

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

85 with self.assertRaises(KeyError): 

86 nkd["c"] = 50 

87 with self.assertRaises(AssertionError): 

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

89 

90 def testDelItem(self): 

91 nkd = NamedKeyDict(self.dictionary) 

92 del nkd[self.a] 

93 self.assertNotIn("a", nkd) 

94 del nkd["b"] 

95 self.assertNotIn(self.b, nkd) 

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

97 

98 def testIter(self): 

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

100 

101 def testEquality(self): 

102 nkd = NamedKeyDict(self.dictionary) 

103 self.assertEqual(nkd, self.dictionary) 

104 self.assertEqual(self.dictionary, nkd) 

105 

106 

107class NamedValueSetTest(unittest.TestCase): 

108 """Tests for NamedValueSet.""" 

109 

110 def setUp(self): 

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

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

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

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

115 

116 def testConstruction(self): 

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

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

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

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

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

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

123 

124 def testNoNameConstruction(self): 

125 with self.assertRaises(AttributeError): 

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

127 

128 def testGetItem(self): 

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

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

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

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

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

134 self.assertIn("a", nvs) 

135 self.assertIn(self.b, nvs) 

136 

137 def testEquality(self): 

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

139 nvs = NamedValueSet(s) 

140 self.assertEqual(nvs, s) 

141 self.assertEqual(s, nvs) 

142 

143 def checkOperator(self, result, expected): 

144 self.assertIsInstance(result, NamedValueSet) 

145 self.assertEqual(result, expected) 

146 

147 def testOperators(self): 

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

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

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

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

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

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

154 

155 def testPop(self): 

156 # Construct with list for repeatable ordering. 

157 nvs = NamedValueSet([self.a, self.b, self.c]) 

158 self.assertEqual(nvs.pop("c"), self.c) 

159 self.assertEqual(nvs.pop(), self.a) 

160 self.assertEqual(nvs.pop(), self.b) 

161 self.assertEqual(nvs.pop("d", self.c), self.c) 

162 with self.assertRaises(KeyError): 

163 nvs.pop() 

164 

165 def testRemove(self): 

166 nvs = NamedValueSet([self.a, self.b, self.c]) 

167 nvs.remove("b") 

168 self.assertIn("a", nvs) 

169 self.assertNotIn("b", nvs) 

170 with self.assertRaises(KeyError): 

171 nvs.remove("d") 

172 nvs.discard("d") 

173 nvs.discard("a") 

174 self.assertNotIn("a", nvs) 

175 

176 

177class GlobToRegexTestCase(unittest.TestCase): 

178 """Tests for glob to regex.""" 

179 

180 def testStarInList(self): 

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

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

183 """ 

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

185 

186 def testGlobList(self): 

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

188 returns in the expected list. 

189 """ 

190 # These strings should be returned unchanged. 

191 strings = ["bar", "😺", "ingésτ", "ex]", "[xe", "[!no", "e[x"] 

192 self.assertEqual(globToRegex(strings), strings) 

193 

194 # Globs with strings that match the glob and strings that do not. 

195 tests = ( 

196 ("bar", ["bar"], ["baz"]), 

197 ("ba*", ["bar", "baz"], ["az"]), 

198 ("ba[rz]", ["bar", "baz"], ["bat"]), 

199 ("ba[rz]x[y", ["barx[y", "bazx[y"], ["batx[y"]), 

200 ("ba[!rz]", ["bat", "baτ"], ["bar", "baz"]), 

201 ("b?r", ["bor", "bar", "b😺r"], ["bat"]), 

202 ("*.fits", ["boz.fits"], ["boz.fits.gz", "boz.hdf5"]), 

203 ) 

204 

205 for glob, matches, no_matches in tests: 

206 patterns = globToRegex(glob) 

207 for match in matches: 

208 self.assertTrue(bool(re.fullmatch(patterns[0], match))) 

209 for no_match in no_matches: 

210 self.assertIsNone(re.fullmatch(patterns[0], no_match)) 

211 

212 

213if __name__ == "__main__": 

214 unittest.main()