Coverage for tests/test_wrappers.py: 12%

350 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-02 06:11 -0800

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 def method1(self): 

21 return self 

22 

23 @classmethod 

24 def method2(cls): 

25 return cls 

26 

27 @staticmethod 

28 def method3(): 

29 return True 

30 

31 @property 

32 def property1(self): 

33 return False 

34 

35 

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

37 def setUp(self): 

38 @lsst.utils.continueClass 

39 class MockClass: 

40 def method1a(self): 

41 return self 

42 

43 @classmethod 

44 def method2a(cls): 

45 return cls 

46 

47 @staticmethod 

48 def method3a(): 

49 return True 

50 

51 @property 

52 def property1a(self): 

53 return False 

54 

55 @lsst.utils.inClass(MockClass) 

56 def method1b(self): 

57 return self 

58 

59 @lsst.utils.inClass(MockClass) 

60 @classmethod 

61 def method2b(cls): 

62 return cls 

63 

64 @lsst.utils.inClass(MockClass) 

65 @staticmethod 

66 def method3b(): 

67 return True 

68 

69 @lsst.utils.inClass(MockClass) 

70 @property 

71 def property1b(self): 

72 return False 

73 

74 def testAttributeCopying(self): 

75 x = MockClass() 

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

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

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

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

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

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

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

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

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

85 self.assertTrue(x.method3()) 

86 self.assertTrue(x.method3a()) 

87 self.assertTrue(x.method3b()) 

88 self.assertTrue(MockClass.method3()) 

89 self.assertTrue(MockClass.method3a()) 

90 self.assertTrue(MockClass.method3b()) 

91 self.assertFalse(x.property1) 

92 self.assertFalse(x.property1a) 

93 self.assertFalse(x.property1b) 

94 

95 

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

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

98 template parameter. 

99 """ 

100 

101 def setUp(self): 

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

103 def method1(self): 

104 return self 

105 

106 @classmethod 

107 def method2(cls): 

108 return cls 

109 

110 @staticmethod 

111 def method3(): 

112 return True 

113 

114 @property 

115 def property1(self): 

116 return False 

117 

118 class ExampleF: 

119 pass 

120 

121 class ExampleD: 

122 pass 

123 

124 self.Example = Example 

125 self.ExampleF = ExampleF 

126 self.ExampleD = ExampleD 

127 

128 def register(self): 

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

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

131 

132 def alias(self): 

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

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

135 

136 def testCorrectRegistration(self): 

137 self.register() 

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

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

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

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

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

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

144 

145 def testAliases(self): 

146 self.register() 

147 self.alias() 

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

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

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

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

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

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

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

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

156 

157 def testInheritanceHooks(self): 

158 self.register() 

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

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

161 f = self.ExampleF() 

162 d = self.ExampleD() 

163 self.assertIsInstance(f, self.Example) 

164 self.assertIsInstance(d, self.Example) 

165 self.assertEqual(set(self.Example.__subclasses__()), set([self.ExampleF, self.ExampleD])) 

166 

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

168 # examples to check. 

169 class ExampleSub(self.ExampleD): 

170 # A subclass that is not itself registered. 

171 pass 

172 

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

174 # A new independent class. 

175 pass 

176 

177 class Example2I: 

178 # Something that will be registered in independent hierarchy. 

179 pass 

180 

181 Example2.register(np.int32, Example2I) 

182 

183 sub = ExampleSub() 

184 self.assertIsInstance(sub, self.Example) 

185 self.assertNotIsInstance(sub, Example2) 

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

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

188 

189 def testConstruction(self): 

190 self.register() 

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

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

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

194 for f in (f1, f2): 

195 self.assertIsInstance(f, self.Example) 

196 self.assertIsInstance(f, self.ExampleF) 

197 self.assertNotIsInstance(f, self.ExampleD) 

198 

199 with self.assertRaises(TypeError): 

200 self.Example() 

201 with self.assertRaises(TypeError): 

202 self.Example(dtype=np.int32) 

203 

204 def testAttributeCopying(self): 

205 self.register() 

206 f = self.ExampleF() 

207 d = self.ExampleD() 

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

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

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

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

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

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

214 self.assertTrue(f.method3()) 

215 self.assertTrue(d.method3()) 

216 self.assertTrue(self.ExampleF.method3()) 

217 self.assertTrue(self.ExampleD.method3()) 

218 self.assertFalse(f.property1) 

219 self.assertFalse(d.property1) 

220 

221 def testDictBehavior(self): 

222 self.register() 

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

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

225 self.assertEqual(set(self.Example.keys()), set([np.float32, np.float64])) 

226 self.assertEqual(set(self.Example.values()), set([self.ExampleF, self.ExampleD])) 

227 self.assertEqual( 

228 set(self.Example.items()), set([(np.float32, self.ExampleF), (np.float64, self.ExampleD)]) 

229 ) 

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

231 self.assertEqual(set(iter(self.Example)), set([np.float32, np.float64])) 

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

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

234 

235 def testNoInheritedDictBehavior(self): 

236 self.register() 

237 f = self.ExampleF() 

238 with self.assertRaises(Exception): # Py2:AttributeError, Py3:TypeError 

239 len(f) 

240 with self.assertRaises(Exception): # Py2:AttributeError, Py3:TypeError 

241 f["F"] 

242 with self.assertRaises(TypeError): 

243 for x in f: 

244 pass 

245 with self.assertRaises(TypeError): 

246 len(self.ExampleF) 

247 with self.assertRaises(TypeError): 

248 self.ExampleF["F"] 

249 with self.assertRaises(TypeError): 

250 for x in self.ExampleF: 

251 pass 

252 

253 def testAliasUnregistered(self): 

254 with self.assertRaises(ValueError): 

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

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

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

258 

259 def testRegisterDTypeTwice(self): 

260 with self.assertRaises(KeyError): 

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

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

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

264 

265 def testRegisterTemplateTwice(self): 

266 with self.assertRaises(ValueError): 

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

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

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

270 

271 

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

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

274 template parameters. 

275 """ 

276 

277 def setUp(self): 

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

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

280 TEMPLATE_DEFAULTS = (2, None) 

281 

282 class Example2F: 

283 pass 

284 

285 class Example2D: 

286 pass 

287 

288 class Example3F: 

289 pass 

290 

291 class Example3D: 

292 pass 

293 

294 self.Example = Example 

295 self.Example2F = Example2F 

296 self.Example2D = Example2D 

297 self.Example3F = Example3F 

298 self.Example3D = Example3D 

299 

300 def register(self): 

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

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

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

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

305 

306 def alias(self): 

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

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

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

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

311 

312 def testCorrectRegistration(self): 

313 self.register() 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

330 

331 def testAliases(self): 

332 self.register() 

333 self.alias() 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

350 

351 def testInheritanceHooks(self): 

352 self.register() 

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

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

355 f = self.Example2F() 

356 d = self.Example3D() 

357 self.assertIsInstance(f, self.Example) 

358 self.assertIsInstance(d, self.Example) 

359 self.assertEqual( 

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

361 set([self.Example2F, self.Example2D, self.Example3F, self.Example3D]), 

362 ) 

363 

364 def testConstruction(self): 

365 self.register() 

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

367 self.assertIsInstance(f, self.Example) 

368 self.assertIsInstance(f, self.Example2F) 

369 with self.assertRaises(TypeError): 

370 self.Example() 

371 with self.assertRaises(TypeError): 

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

373 

374 def testDictBehavior(self): 

375 self.register() 

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

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

378 self.assertEqual( 

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

380 set([(2, np.float32), (2, np.float64), (3, np.float32), (3, np.float64)]), 

381 ) 

382 self.assertEqual( 

383 set(self.Example.values()), set([self.Example2F, self.Example2D, self.Example3F, self.Example3D]) 

384 ) 

385 self.assertEqual( 

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

387 set( 

388 [ 

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

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

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

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

393 ] 

394 ), 

395 ) 

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

397 self.assertEqual( 

398 set(iter(self.Example)), set([(2, np.float32), (2, np.float64), (3, np.float32), (3, np.float64)]) 

399 ) 

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

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

402 

403 def testRegisterBadKey(self): 

404 with self.assertRaises(ValueError): 

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

406 

407 def testRegisterDTypeTwice(self): 

408 with self.assertRaises(KeyError): 

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

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

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

412 

413 def testRegisterTemplateTwice(self): 

414 with self.assertRaises(ValueError): 

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

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

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

418 

419 

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

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

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

423 """ 

424 

425 def setUp(self): 

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

427 TEMPLATE_PARAMS = ("dtype",) 

428 TEMPLATE_DEFAULTS = (np.float32,) 

429 

430 class ExampleF: 

431 @staticmethod 

432 def staticCall(): 

433 return 6 

434 

435 @classmethod 

436 def classCall(cls): 

437 return cls 

438 

439 def regularCall(self): 

440 return self 

441 

442 class ExampleI: 

443 @staticmethod 

444 def notTransferedStaticCall(): 

445 return 8 

446 

447 @classmethod 

448 def notTransferedClassCall(cls): 

449 return cls 

450 

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

452 # static methods from c++ 

453 setattr(ExampleF, "pow", pow) 

454 

455 Example.register(np.float32, ExampleF) 

456 Example.register(np.int32, ExampleI) 

457 self.Example = Example 

458 self.ExampleF = ExampleF 

459 self.ExampleI = ExampleI 

460 

461 def testMethodCopyForDefaultType(self): 

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

463 # the regular method was not 

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

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

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

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

468 

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

470 # correct values 

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

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

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

474 

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

476 # transfered 

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

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

479 

480 

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

482 unittest.main()