Coverage for tests/test_wrappers.py: 11%

348 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-08 09:53 +0000

1# This file is part of utils. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12import unittest 

13 

14import lsst.utils 

15import lsst.utils.tests 

16import numpy as np 

17 

18 

19class MockClass: # continued class needs to be at module scope 

20 """A test class that can be continued.""" 

21 

22 def method1(self): 

23 return self 

24 

25 @classmethod 

26 def method2(cls): 

27 return cls 

28 

29 @staticmethod 

30 def method3(): 

31 return True 

32 

33 @property 

34 def property1(self): 

35 return False 

36 

37 

38class DecoratorsTestCase(lsst.utils.tests.TestCase): 

39 """Test the decorators.""" 

40 

41 def setUp(self): 

42 @lsst.utils.continueClass 

43 class MockClass: 

44 def method1a(self): 

45 return self 

46 

47 @classmethod 

48 def method2a(cls): 

49 return cls 

50 

51 @staticmethod 

52 def method3a(): 

53 return True 

54 

55 @property 

56 def property1a(self): 

57 return False 

58 

59 @lsst.utils.inClass(MockClass) 

60 def method1b(self): 

61 return self 

62 

63 @lsst.utils.inClass(MockClass) 

64 @classmethod 

65 def method2b(cls): 

66 return cls 

67 

68 @lsst.utils.inClass(MockClass) 

69 @staticmethod 

70 def method3b(): 

71 return True 

72 

73 @lsst.utils.inClass(MockClass) 

74 @property 

75 def property1b(self): 

76 return False 

77 

78 def testAttributeCopying(self): 

79 x = MockClass() 

80 self.assertIs(x.method1(), x) 

81 self.assertIs(x.method1a(), x) 

82 self.assertIs(x.method1b(), x) 

83 self.assertIs(x.method2(), MockClass) 

84 self.assertIs(x.method2a(), MockClass) 

85 self.assertIs(x.method2b(), MockClass) 

86 self.assertIs(MockClass.method2(), MockClass) 

87 self.assertIs(MockClass.method2a(), MockClass) 

88 self.assertIs(MockClass.method2b(), MockClass) 

89 self.assertTrue(x.method3()) 

90 self.assertTrue(x.method3a()) 

91 self.assertTrue(x.method3b()) 

92 self.assertTrue(MockClass.method3()) 

93 self.assertTrue(MockClass.method3a()) 

94 self.assertTrue(MockClass.method3b()) 

95 self.assertFalse(x.property1) 

96 self.assertFalse(x.property1a) 

97 self.assertFalse(x.property1b) 

98 

99 

100class TemplateMetaSimpleTestCase(lsst.utils.tests.TestCase): 

101 """Test TemplateMeta on a mockup of a template with a single dtype 

102 template parameter. 

103 """ 

104 

105 def setUp(self): 

106 class Example(metaclass=lsst.utils.TemplateMeta): 

107 def method1(self): 

108 return self 

109 

110 @classmethod 

111 def method2(cls): 

112 return cls 

113 

114 @staticmethod 

115 def method3(): 

116 return True 

117 

118 @property 

119 def property1(self): 

120 return False 

121 

122 class ExampleF: 

123 pass 

124 

125 class ExampleD: 

126 pass 

127 

128 self.Example = Example 

129 self.ExampleF = ExampleF 

130 self.ExampleD = ExampleD 

131 

132 def register(self): 

133 self.Example.register(np.float32, self.ExampleF) 

134 self.Example.register(np.float64, self.ExampleD) 

135 

136 def alias(self): 

137 self.Example.alias("F", self.ExampleF) 

138 self.Example.alias("D", self.ExampleD) 

139 

140 def testCorrectRegistration(self): 

141 self.register() 

142 self.assertEqual(self.ExampleF.dtype, np.float32) 

143 self.assertEqual(self.ExampleD.dtype, np.float64) 

144 self.assertIn(np.float32, self.Example) 

145 self.assertIn(np.float64, self.Example) 

146 self.assertEqual(self.Example[np.float32], self.ExampleF) 

147 self.assertEqual(self.Example[np.float64], self.ExampleD) 

148 

149 def testAliases(self): 

150 self.register() 

151 self.alias() 

152 self.assertEqual(self.ExampleF.dtype, np.float32) 

153 self.assertEqual(self.ExampleD.dtype, np.float64) 

154 self.assertIn("F", self.Example) 

155 self.assertIn("D", self.Example) 

156 self.assertEqual(self.Example["F"], self.ExampleF) 

157 self.assertEqual(self.Example["D"], self.ExampleD) 

158 self.assertEqual(self.Example["F"], self.Example[np.float32]) 

159 self.assertEqual(self.Example["D"], self.Example[np.float64]) 

160 

161 def testInheritanceHooks(self): 

162 self.register() 

163 self.assertTrue(issubclass(self.ExampleF, self.Example)) 

164 self.assertTrue(issubclass(self.ExampleD, self.Example)) 

165 f = self.ExampleF() 

166 d = self.ExampleD() 

167 self.assertIsInstance(f, self.Example) 

168 self.assertIsInstance(d, self.Example) 

169 self.assertEqual(set(self.Example.__subclasses__()), {self.ExampleF, self.ExampleD}) 

170 

171 # To test fallback code path, ensure that there are multiple 

172 # examples to check. 

173 class ExampleSub(self.ExampleD): 

174 # A subclass that is not itself registered. 

175 pass 

176 

177 class Example2(metaclass=lsst.utils.TemplateMeta): 

178 # A new independent class. 

179 pass 

180 

181 class Example2I: 

182 # Something that will be registered in independent hierarchy. 

183 pass 

184 

185 Example2.register(np.int32, Example2I) 

186 

187 sub = ExampleSub() 

188 self.assertIsInstance(sub, self.Example) 

189 self.assertNotIsInstance(sub, Example2) 

190 self.assertTrue(issubclass(ExampleSub, self.Example)) 

191 self.assertFalse(issubclass(ExampleSub, Example2)) 

192 

193 def testConstruction(self): 

194 self.register() 

195 f1 = self.Example(dtype=np.float32) 

196 # Test that numpy dtype objects resolve to their underlying type 

197 f2 = self.Example(dtype=np.dtype(np.float32)) 

198 for f in (f1, f2): 

199 self.assertIsInstance(f, self.Example) 

200 self.assertIsInstance(f, self.ExampleF) 

201 self.assertNotIsInstance(f, self.ExampleD) 

202 

203 with self.assertRaises(TypeError): 

204 self.Example() 

205 with self.assertRaises(TypeError): 

206 self.Example(dtype=np.int32) 

207 

208 def testAttributeCopying(self): 

209 self.register() 

210 f = self.ExampleF() 

211 d = self.ExampleD() 

212 self.assertIs(f.method1(), f) 

213 self.assertIs(d.method1(), d) 

214 self.assertIs(f.method2(), self.ExampleF) 

215 self.assertIs(d.method2(), self.ExampleD) 

216 self.assertIs(self.ExampleF.method2(), self.ExampleF) 

217 self.assertIs(self.ExampleD.method2(), self.ExampleD) 

218 self.assertTrue(f.method3()) 

219 self.assertTrue(d.method3()) 

220 self.assertTrue(self.ExampleF.method3()) 

221 self.assertTrue(self.ExampleD.method3()) 

222 self.assertFalse(f.property1) 

223 self.assertFalse(d.property1) 

224 

225 def testDictBehavior(self): 

226 self.register() 

227 self.assertIn(np.float32, self.Example) 

228 self.assertEqual(self.Example[np.float32], self.ExampleF) 

229 self.assertEqual(set(self.Example.keys()), {np.float32, np.float64}) 

230 self.assertEqual(set(self.Example.values()), {self.ExampleF, self.ExampleD}) 

231 self.assertEqual( 

232 set(self.Example.items()), {(np.float32, self.ExampleF), (np.float64, self.ExampleD)} 

233 ) 

234 self.assertEqual(len(self.Example), 2) 

235 self.assertEqual(set(iter(self.Example)), {np.float32, np.float64}) 

236 self.assertEqual(self.Example.get(np.float64), self.ExampleD) 

237 self.assertEqual(self.Example.get(np.int32, False), False) 

238 

239 def testNoInheritedDictBehavior(self): 

240 self.register() 

241 f = self.ExampleF() 

242 with self.assertRaises(TypeError): 

243 len(f) 

244 with self.assertRaises(TypeError): 

245 f["F"] 

246 with self.assertRaises(TypeError): 

247 for _ in f: 

248 pass 

249 with self.assertRaises(TypeError): 

250 len(self.ExampleF) 

251 with self.assertRaises(TypeError): 

252 self.ExampleF["F"] 

253 with self.assertRaises(TypeError): 

254 for _ in self.ExampleF: 

255 pass 

256 

257 def testAliasUnregistered(self): 

258 with self.assertRaises(ValueError): 

259 self.Example.alias("F", self.ExampleF) 

260 self.assertEqual(len(self.Example), 0) 

261 self.assertEqual(len(self.Example), 0) 

262 

263 def testRegisterDTypeTwice(self): 

264 with self.assertRaises(KeyError): 

265 self.Example.register("F", self.ExampleF) 

266 self.Example.register("F", self.ExampleD) 

267 self.assertEqual(len(self.Example), 1) 

268 

269 def testRegisterTemplateTwice(self): 

270 with self.assertRaises(ValueError): 

271 self.Example.register("F", self.ExampleF) 

272 self.Example.register("D", self.ExampleF) 

273 self.assertEqual(len(self.Example), 1) 

274 

275 

276class TemplateMetaHardTestCase(lsst.utils.tests.TestCase): 

277 """Test TemplateMeta with a mockup of a template with multiple 

278 template parameters. 

279 """ 

280 

281 def setUp(self): 

282 class Example(metaclass=lsst.utils.TemplateMeta): 

283 TEMPLATE_PARAMS = ("d", "u") 

284 TEMPLATE_DEFAULTS = (2, None) 

285 

286 class Example2F: 

287 pass 

288 

289 class Example2D: 

290 pass 

291 

292 class Example3F: 

293 pass 

294 

295 class Example3D: 

296 pass 

297 

298 self.Example = Example 

299 self.Example2F = Example2F 

300 self.Example2D = Example2D 

301 self.Example3F = Example3F 

302 self.Example3D = Example3D 

303 

304 def register(self): 

305 self.Example.register((2, np.float32), self.Example2F) 

306 self.Example.register((2, np.float64), self.Example2D) 

307 self.Example.register((3, np.float32), self.Example3F) 

308 self.Example.register((3, np.float64), self.Example3D) 

309 

310 def alias(self): 

311 self.Example.alias("2F", self.Example2F) 

312 self.Example.alias("2D", self.Example2D) 

313 self.Example.alias("3F", self.Example3F) 

314 self.Example.alias("3D", self.Example3D) 

315 

316 def testCorrectRegistration(self): 

317 self.register() 

318 self.assertEqual(self.Example2F.d, 2) 

319 self.assertEqual(self.Example2F.u, np.float32) 

320 self.assertEqual(self.Example2D.d, 2) 

321 self.assertEqual(self.Example2D.u, np.float64) 

322 self.assertEqual(self.Example3F.d, 3) 

323 self.assertEqual(self.Example3F.u, np.float32) 

324 self.assertEqual(self.Example3D.d, 3) 

325 self.assertEqual(self.Example3D.u, np.float64) 

326 self.assertIn((2, np.float32), self.Example) 

327 self.assertIn((2, np.float64), self.Example) 

328 self.assertIn((3, np.float32), self.Example) 

329 self.assertIn((3, np.float64), self.Example) 

330 self.assertEqual(self.Example[2, np.float32], self.Example2F) 

331 self.assertEqual(self.Example[2, np.float64], self.Example2D) 

332 self.assertEqual(self.Example[3, np.float32], self.Example3F) 

333 self.assertEqual(self.Example[3, np.float64], self.Example3D) 

334 

335 def testAliases(self): 

336 self.register() 

337 self.alias() 

338 self.assertEqual(self.Example2F.d, 2) 

339 self.assertEqual(self.Example2F.u, np.float32) 

340 self.assertEqual(self.Example2D.d, 2) 

341 self.assertEqual(self.Example2D.u, np.float64) 

342 self.assertEqual(self.Example3F.d, 3) 

343 self.assertEqual(self.Example3F.u, np.float32) 

344 self.assertEqual(self.Example3D.d, 3) 

345 self.assertEqual(self.Example3D.u, np.float64) 

346 self.assertIn("2F", self.Example) 

347 self.assertIn("2D", self.Example) 

348 self.assertIn("3F", self.Example) 

349 self.assertIn("3D", self.Example) 

350 self.assertEqual(self.Example["2F"], self.Example2F) 

351 self.assertEqual(self.Example["2D"], self.Example2D) 

352 self.assertEqual(self.Example["3F"], self.Example3F) 

353 self.assertEqual(self.Example["3D"], self.Example3D) 

354 

355 def testInheritanceHooks(self): 

356 self.register() 

357 self.assertTrue(issubclass(self.Example2F, self.Example)) 

358 self.assertTrue(issubclass(self.Example3D, self.Example)) 

359 f = self.Example2F() 

360 d = self.Example3D() 

361 self.assertIsInstance(f, self.Example) 

362 self.assertIsInstance(d, self.Example) 

363 self.assertEqual( 

364 set(self.Example.__subclasses__()), 

365 {self.Example2F, self.Example2D, self.Example3F, self.Example3D}, 

366 ) 

367 

368 def testConstruction(self): 

369 self.register() 

370 f = self.Example(u=np.float32) 

371 self.assertIsInstance(f, self.Example) 

372 self.assertIsInstance(f, self.Example2F) 

373 with self.assertRaises(TypeError): 

374 self.Example() 

375 with self.assertRaises(TypeError): 

376 self.Example(u=np.int32, d=1) 

377 

378 def testDictBehavior(self): 

379 self.register() 

380 self.assertIn((2, np.float32), self.Example) 

381 self.assertEqual(self.Example[2, np.float32], self.Example2F) 

382 self.assertEqual( 

383 set(self.Example.keys()), 

384 {(2, np.float32), (2, np.float64), (3, np.float32), (3, np.float64)}, 

385 ) 

386 self.assertEqual( 

387 set(self.Example.values()), {self.Example2F, self.Example2D, self.Example3F, self.Example3D} 

388 ) 

389 self.assertEqual( 

390 set(self.Example.items()), 

391 { 

392 ((2, np.float32), self.Example2F), 

393 ((2, np.float64), self.Example2D), 

394 ((3, np.float32), self.Example3F), 

395 ((3, np.float64), self.Example3D), 

396 }, 

397 ) 

398 self.assertEqual(len(self.Example), 4) 

399 self.assertEqual( 

400 set(iter(self.Example)), {(2, np.float32), (2, np.float64), (3, np.float32), (3, np.float64)} 

401 ) 

402 self.assertEqual(self.Example.get((3, np.float64)), self.Example3D) 

403 self.assertEqual(self.Example.get((2, np.int32), False), False) 

404 

405 def testRegisterBadKey(self): 

406 with self.assertRaises(ValueError): 

407 self.Example.register("F", self.Example2F) 

408 

409 def testRegisterDTypeTwice(self): 

410 with self.assertRaises(KeyError): 

411 self.Example.register((2, "F"), self.Example2F) 

412 self.Example.register((2, "F"), self.Example2D) 

413 self.assertEqual(len(self.Example), 1) 

414 

415 def testRegisterTemplateTwice(self): 

416 with self.assertRaises(ValueError): 

417 self.Example.register((2, "F"), self.Example2F) 

418 self.Example.register((2, "D"), self.Example2F) 

419 self.assertEqual(len(self.Example), 1) 

420 

421 

422class TestDefaultMethodCopying(lsst.utils.tests.TestCase): 

423 """Test to determine if static and class methods from a class which is 

424 registered as a default type in a type ABC are properly copied. 

425 """ 

426 

427 def setUp(self): 

428 class Example(metaclass=lsst.utils.TemplateMeta): 

429 TEMPLATE_PARAMS = ("dtype",) 

430 TEMPLATE_DEFAULTS = (np.float32,) 

431 

432 class ExampleF: 

433 @staticmethod 

434 def staticCall(): 

435 return 6 

436 

437 @classmethod 

438 def classCall(cls): 

439 return cls 

440 

441 def regularCall(self): 

442 return self 

443 

444 class ExampleI: 

445 @staticmethod 

446 def notTransferedStaticCall(): 

447 return 8 

448 

449 @classmethod 

450 def notTransferedClassCall(cls): 

451 return cls 

452 

453 # Add in a built in function to ExampleF to mimic how pybind11 treats 

454 # static methods from c++. 

455 ExampleF.pow = pow 

456 

457 Example.register(np.float32, ExampleF) 

458 Example.register(np.int32, ExampleI) 

459 self.Example = Example 

460 self.ExampleF = ExampleF 

461 self.ExampleI = ExampleI 

462 

463 def testMethodCopyForDefaultType(self): 

464 # Check that the methods for the default type were transfered and that 

465 # the regular method was not 

466 self.assertTrue(hasattr(self.Example, "staticCall")) 

467 self.assertTrue(hasattr(self.Example, "pow")) 

468 self.assertTrue(hasattr(self.Example, "classCall")) 

469 self.assertFalse(hasattr(self.Example, "regularCall")) 

470 

471 # Verify the default static and class method defaults return the 

472 # correct values 

473 self.assertEqual(self.Example.staticCall(), 6) 

474 self.assertEqual(self.Example.pow(2, 2), 4) 

475 self.assertIs(self.Example.classCall(), self.ExampleF) 

476 

477 # Verify static and class methods for non default keys are not 

478 # transfered 

479 self.assertFalse(hasattr(self.Example, "notTransferedStaticCall")) 

480 self.assertFalse(hasattr(self.Example, "notTransferedClassCall")) 

481 

482 

483if __name__ == "__main__": 

484 unittest.main()