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
« 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.
12import unittest
14import lsst.utils
15import lsst.utils.tests
16import numpy as np
19class MockClass: # continued class needs to be at module scope
20 """A test class that can be continued."""
22 def method1(self):
23 return self
25 @classmethod
26 def method2(cls):
27 return cls
29 @staticmethod
30 def method3():
31 return True
33 @property
34 def property1(self):
35 return False
38class DecoratorsTestCase(lsst.utils.tests.TestCase):
39 """Test the decorators."""
41 def setUp(self):
42 @lsst.utils.continueClass
43 class MockClass:
44 def method1a(self):
45 return self
47 @classmethod
48 def method2a(cls):
49 return cls
51 @staticmethod
52 def method3a():
53 return True
55 @property
56 def property1a(self):
57 return False
59 @lsst.utils.inClass(MockClass)
60 def method1b(self):
61 return self
63 @lsst.utils.inClass(MockClass)
64 @classmethod
65 def method2b(cls):
66 return cls
68 @lsst.utils.inClass(MockClass)
69 @staticmethod
70 def method3b():
71 return True
73 @lsst.utils.inClass(MockClass)
74 @property
75 def property1b(self):
76 return False
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)
100class TemplateMetaSimpleTestCase(lsst.utils.tests.TestCase):
101 """Test TemplateMeta on a mockup of a template with a single dtype
102 template parameter.
103 """
105 def setUp(self):
106 class Example(metaclass=lsst.utils.TemplateMeta):
107 def method1(self):
108 return self
110 @classmethod
111 def method2(cls):
112 return cls
114 @staticmethod
115 def method3():
116 return True
118 @property
119 def property1(self):
120 return False
122 class ExampleF:
123 pass
125 class ExampleD:
126 pass
128 self.Example = Example
129 self.ExampleF = ExampleF
130 self.ExampleD = ExampleD
132 def register(self):
133 self.Example.register(np.float32, self.ExampleF)
134 self.Example.register(np.float64, self.ExampleD)
136 def alias(self):
137 self.Example.alias("F", self.ExampleF)
138 self.Example.alias("D", self.ExampleD)
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)
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])
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})
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
177 class Example2(metaclass=lsst.utils.TemplateMeta):
178 # A new independent class.
179 pass
181 class Example2I:
182 # Something that will be registered in independent hierarchy.
183 pass
185 Example2.register(np.int32, Example2I)
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))
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)
203 with self.assertRaises(TypeError):
204 self.Example()
205 with self.assertRaises(TypeError):
206 self.Example(dtype=np.int32)
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)
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)
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
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)
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)
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)
276class TemplateMetaHardTestCase(lsst.utils.tests.TestCase):
277 """Test TemplateMeta with a mockup of a template with multiple
278 template parameters.
279 """
281 def setUp(self):
282 class Example(metaclass=lsst.utils.TemplateMeta):
283 TEMPLATE_PARAMS = ("d", "u")
284 TEMPLATE_DEFAULTS = (2, None)
286 class Example2F:
287 pass
289 class Example2D:
290 pass
292 class Example3F:
293 pass
295 class Example3D:
296 pass
298 self.Example = Example
299 self.Example2F = Example2F
300 self.Example2D = Example2D
301 self.Example3F = Example3F
302 self.Example3D = Example3D
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)
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)
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)
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)
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 )
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)
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)
405 def testRegisterBadKey(self):
406 with self.assertRaises(ValueError):
407 self.Example.register("F", self.Example2F)
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)
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)
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 """
427 def setUp(self):
428 class Example(metaclass=lsst.utils.TemplateMeta):
429 TEMPLATE_PARAMS = ("dtype",)
430 TEMPLATE_DEFAULTS = (np.float32,)
432 class ExampleF:
433 @staticmethod
434 def staticCall():
435 return 6
437 @classmethod
438 def classCall(cls):
439 return cls
441 def regularCall(self):
442 return self
444 class ExampleI:
445 @staticmethod
446 def notTransferedStaticCall():
447 return 8
449 @classmethod
450 def notTransferedClassCall(cls):
451 return cls
453 # Add in a built in function to ExampleF to mimic how pybind11 treats
454 # static methods from c++.
455 ExampleF.pow = pow
457 Example.register(np.float32, ExampleF)
458 Example.register(np.int32, ExampleI)
459 self.Example = Example
460 self.ExampleF = ExampleF
461 self.ExampleI = ExampleI
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"))
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)
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"))
483if __name__ == "__main__":
484 unittest.main()