LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
testUtils.py
Go to the documentation of this file.
1 # This file is part of afw.
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 # 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 <https://www.gnu.org/licenses/>.
21 
22 __all__ = []
23 
24 from collections import Counter
25 
26 import numpy as np
27 
28 import lsst.utils.tests
29 
30 from lsst.afw.typehandling import Storable
31 
32 
33 class GenericMapTestBaseClass(lsst.utils.tests.TestCase):
34  """Base class for unit tests of GenericMap.
35 
36  Subclasses must call `GenericMapTestBaseClass.setUp(self)`
37  if they provide their own version.
38 
39  This class is not *quite* a generic Mapping testbed, because it assumes
40  that the map being tested only accepts keys of a particular type, stored as
41  the `dtype` member.
42  """
43 
45  """A subclass of Storable for testing purposes.
46  """
47  def __repr__(self):
48  return "Simplest possible representation"
49 
50  def __hash__(self):
51  return 100
52 
53  def __eq__(self, other):
54  """Warning: violates both substitution and equality symmetry!
55  """
56  return self.__class____class__ == other.__class__
57 
59  """A subclass of Storable for testing purposes.
60  """
61  def __init__(self, storage):
62  super().__init__()
63  self._storage_storage = storage
64 
65  def __repr__(self):
66  return f"ComplexStorable({self._storage!r})"
67 
68  def __hash__(self):
69  return hash(self._storage_storage)
70 
71  def __eq__(self, other):
72  """Warning: violates both substitution and equality symmetry!
73  """
74  if self.__class____class____class__ == other.__class__:
75  return self._storage_storage == other._storage
76  else:
77  return False
78 
79  class NotAStorable:
80  """A class that should not be a legal value in a GenericMap.
81  """
82  def __str__(self):
83  return "Non-Storable"
84 
85  _testData = {
86  0: True,
87  1: 42,
88  2: 42.0,
89  3: "How many roads must a man walk down?",
90  4: SimpleStorable(),
91  5: ComplexStorable(-100.0),
92  6: None,
93  }
94 
95  @classmethod
96  def getTestData(cls, keyClass):
97  """Generic dataset for testing GenericMap classes that can handle it.
98 
99  Parameters
100  ----------
101  keyClass : `type`
102  The type of key expected by the GenericMap.
103  """
104  return {keyClass(key): value for key, value in cls._testData_testData.items()}
105 
106  @staticmethod
107  def getValidKeys(mapClass):
108  """Return all keys suitable for a GenericMap.
109 
110  Parameters
111  ----------
112  mapClass : `type`
113  A type object for a subclass of either `GenericMap` or a
114  key-specific specialization.
115 
116  Returns
117  -------
118  keyTypes: `set` [`type`]
119  The types that can be used as keys. If ``mapClass`` is a
120  key-specific specialization, this set will contain exactly
121  one type.
122  """
123  try:
124  return {mapClass.dtype}
125  except AttributeError:
126  return {cls.dtype for cls in mapClass.__subclasses__()}
127 
128  def setUp(self):
129  """Set up a test
130 
131  Subclasses must call this method if they override setUp.
132  """
133  super().setUp()
134  # tell unittest to use the msg argument of asserts as a supplement
135  # to the error message, rather than as the whole error message
136  self.longMessagelongMessage = True
137 
138  # Mapping must have:
139  # __str__
140  # __repr__
141  # __eq__
142  # __ne__
143  # __contains__
144  # __getitem__
145  # get
146  # __iter__
147  # __len__
148  # __bool__
149  # keys
150  # items
151  # values
152 
153  def checkInitMapping(self, mapClass, contents, msg=""):
154  """Check initialization from a mapping.
155 
156  Parameters
157  ----------
158  mapClass : `lsst.afw.typehandling.GenericMap`-type
159  The class whose ``__init__`` method will be tested.
160  contents : `Mapping`
161  The key-value pairs to insert into the map
162  msg : `str`
163  Error message suffix describing test parameters
164  """
165  for keyType in self.getValidKeysgetValidKeys(mapClass):
166  genericMap = mapClass(contents)
167  self.checkContentscheckContents(genericMap, contents, msg=msg)
168 
169  extraContents = {key: value for key, value in contents.items()} # contents need not define copy()
170  extraKey = keyType(101)
171  extraValue = 'Extra value'
172  extraContents[extraKey] = extraValue
173  genericMap = mapClass(contents, **{keyType(101): extraValue})
174  self.checkContentscheckContents(genericMap, extraContents, msg=msg)
175 
176  with self.assertRaises(TypeError, msg=msg):
177  mapClass({keyType(0): GenericMapTestBaseClass.NotAStorable()})
178 
179  def checkInitPairs(self, mapClass, contents, msg=""):
180  """Check initialization from an iterable of pairs.
181 
182  Parameters
183  ----------
184  mapClass: `lsst.afw.typehandling.GenericMap`-type
185  The class whose ``__init__`` method will be tested.
186  contents : `Mapping`
187  The key-value pairs to insert into the map
188  msg : `str`
189  Error message suffix describing test parameters
190  """
191  for keyType in self.getValidKeysgetValidKeys(mapClass):
192  genericMap = mapClass(contents.items())
193  self.checkContentscheckContents(genericMap, contents, msg=msg)
194 
195  extraContents = {key: value for key, value in contents.items()} # contents need not define copy()
196  extraKey = keyType(101)
197  extraValue = 'Extra value'
198  extraContents[extraKey] = extraValue
199  genericMap = mapClass(contents.items(), **{keyType(101): extraValue})
200  self.checkContentscheckContents(genericMap, extraContents, msg=msg)
201 
202  with self.assertRaises(TypeError, msg=msg):
203  mapClass([(keyType(0), GenericMapTestBaseClass.NotAStorable())])
204 
205  def checkInitKwargs(self, mapClass, contents, msg=""):
206  """Check bulk insertion from keywords into a GenericMap.
207 
208  Parameters
209  ----------
210  mapClass: `lsst.afw.typehandling.GenericMapS`-type
211  The class whose ``__init__`` method will be tested.
212  Must allow string keys.
213  contents : `Mapping`
214  The key-value pairs to insert into the map
215  msg : `str`
216  Error message suffix describing test parameters
217  """
218  genericMap = mapClass(**contents)
219  self.checkContentscheckContents(genericMap, contents, msg=msg)
220 
221  with self.assertRaises(TypeError, msg=msg):
222  mapClass(notAKey=GenericMapTestBaseClass.NotAStorable())
223 
224  def checkFromKeysDefault(self, mapClass, keys, msg=""):
225  """Check initialization using the ``fromkeys`` factory.
226 
227  Unlike `checkFromKeys`, this method lets ``fromkeys`` use its default
228  value (which may give different behavior, in nonconforming
229  implementations, from explicitly passing `None`).
230 
231  Parameters
232  ----------
233  mapClass: `lsst.afw.typehandling.GenericMap`-type
234  The class whose ``fromkeys`` method will be tested.
235  keys : `iterable`
236  The keys to insert into the map.
237  msg : `str`
238  Error message suffix describing test parameters
239  """
240  genericMap = mapClass.fromkeys(keys)
241  self.assertIsInstance(genericMap, mapClass, msg=msg)
242  self.checkContentscheckContents(genericMap, dict.fromkeys(keys), msg=msg)
243 
244  def checkFromKeys(self, mapClass, keys, value, msg=""):
245  """Check initialization using the ``fromkeys`` factory.
246 
247  Parameters
248  ----------
249  mapClass: `lsst.afw.typehandling.GenericMap`-type
250  The class whose ``fromkeys`` method will be tested.
251  keys : `iterable`
252  The keys to insert into the map.
253  value
254  A legal value for a GenericMap.
255  msg : `str`
256  Error message suffix describing test parameters
257  """
258  genericMap = mapClass.fromkeys(keys, value)
259  self.assertIsInstance(genericMap, mapClass, msg=msg)
260  self.checkContentscheckContents(genericMap, dict.fromkeys(keys, value), msg=msg)
261 
262  def checkContains(self, genericMap, contents, msg=""):
263  """Check the contents of a GenericMap.
264 
265  Parameters
266  ----------
267  genericMap : `lsst.afw.typehandling.GenericMap`
268  The map to test.
269  contents : `Mapping`
270  The key-value pairs that should be present in ``genericMap``
271  msg : `str`
272  Error message suffix describing test parameters
273  """
274  for key in contents:
275  self.assertIn(key, genericMap, msg=msg)
276 
277  keyType = genericMap.dtype
278  for key in range(30):
279  if keyType(key) not in contents:
280  self.assertNotIn(keyType(key), genericMap, msg=msg)
281 
282  wrongType = float if keyType is not float else int
283  with self.assertRaises(TypeError):
284  wrongType(0) in genericMap
285 
286  def checkContents(self, genericMap, contents, msg=""):
287  """Check the contents of a GenericMap.
288 
289  Parameters
290  ----------
291  genericMap : `lsst.afw.typehandling.GenericMap`
292  The map to test.
293  contents : `Mapping`
294  The key-value pairs that should be present in ``genericMap``
295  msg : `str`
296  Error message suffix describing test parameters
297  """
298  for key, value in contents.items():
299  self.assertEqual(genericMap[key], value, msg=msg)
300 
301  keyType = genericMap.dtype
302  for key in (keyType(key) for key in range(30) if keyType(key) not in contents):
303  with self.assertRaises(KeyError, msg=msg):
304  genericMap[key]
305 
306  wrongType = float if keyType is not float else int
307  with self.assertRaises(TypeError):
308  genericMap[wrongType(0)]
309 
310  def checkGet(self, genericMap, contents, msg=""):
311  """Check that GenericMap.get works correctly.
312 
313  Parameters
314  ----------
315  genericMap : `lsst.afw.typehandling.GenericMap`
316  The map to test.
317  contents : `Mapping`
318  The key-value pairs that should be present in ``genericMap``
319  msg : `str`
320  Error message suffix describing test parameters
321  """
322  default = "Not a default value"
323  for key, value in contents.items():
324  self.assertEqual(genericMap.get(key), value, msg=msg)
325  self.assertEqual(genericMap.get(key, default), value, msg=msg)
326 
327  keyType = genericMap.dtype
328  for key in (keyType(key) for key in range(30) if keyType(key) not in contents):
329  self.assertEqual(genericMap.get(key), None, msg=msg)
330  self.assertEqual(genericMap.get(key, default), default, msg=msg)
331 
332  wrongType = float if keyType is not float else int
333  with self.assertRaises(TypeError):
334  genericMap.get(wrongType(0))
335 
336  def checkIteration(self, genericMap, contents, msg=""):
337  """Check the result of iterating over a GenericMap.
338 
339  Parameters
340  ----------
341  genericMap : `lsst.afw.typehandling.GenericMap`
342  The map to test.
343  contents : `Mapping`
344  The key-value pairs that should be present in ``genericMap``
345  msg : `str`
346  Error message suffix describing test parameters
347  """
348  self.assertEqual({key: genericMap[key] for key in genericMap}, dict(contents), msg=msg)
349 
350  def checkViews(self, genericMap, contents, msg=""):
351  """Check the views provided by a GenericMap.
352 
353  Parameters
354  ----------
355  genericMap : `lsst.afw.typehandling.GenericMap`
356  The map to test.
357  contents : `Mapping`
358  The key-value pairs that should be present in ``genericMap``
359  msg : `str`
360  Error message suffix describing test parameters
361  """
362  self.assertEqual(set(genericMap.keys()), set(contents.keys()), msg=msg)
363  self.assertEqual(Counter(genericMap.values()), Counter(contents.values()), msg=msg)
364  self.assertEqual(Counter(genericMap.items()), Counter(contents.items()), msg=msg)
365 
366 
368  """Base class for unit tests of GenericMap that allow insertion/deletion.
369 
370  Subclasses must call `MutableGenericMapTestBaseClass.setUp(self)`
371  if they provide their own version.
372  """
373 
374  @classmethod
375  def _fillMap(cls, mapFactory, contents):
376  """Create a new GenericMap with particular contents.
377 
378  Parameters
379  ----------
380  mapFactory : callable
381  A zero-argument callable that creates an empty
382  `lsst.afw.typehandling.GenericMap` object
383  contents : `Mapping`
384  The key-value pairs that should be present in the new map.
385 
386  Returns
387  -------
388  map : `lsst.afw.typehandling.GenericMap`
389  a GenericMap equivalent to ``contents``
390  """
391  return cls._fillPartialMap_fillPartialMap(mapFactory, contents, len(contents))
392 
393  @classmethod
394  def _fillPartialMap(cls, mapFactory, contents, numElements):
395  """Create a new GenericMap with particular contents.
396 
397  Parameters
398  ----------
399  mapFactory : callable
400  A zero-argument callable that creates an empty
401  `lsst.afw.typehandling.GenericMap` object
402  contents : `Mapping`
403  The key-value pairs that should be present in the new map.
404  numElements : `int`
405  The number of elements from ``contents`` to be inserted.
406 
407  Returns
408  -------
409  map : `lsst.afw.typehandling.GenericMap`
410  a GenericMap containing ``numElements`` of ``contents`` or all of
411  ``contents``, whichever is smaller
412  """
413  newMap = mapFactory()
414  for i, (key, value) in enumerate(contents.items()):
415  if i < numElements:
416  newMap[key] = value
417  else:
418  break
419  return newMap
420 
421  # MutableMapping must have:
422  # __setitem__
423  # setdefault
424  # __delitem__
425  # pop
426  # popitem
427  # clear
428  # update
429 
430  def checkInsertItem(self, mapFactory, contents, msg=""):
431  """Check element insertion in a GenericMap.
432 
433  Parameters
434  ----------
435  mapFactory : callable
436  A zero-argument callable that creates an empty
437  `lsst.afw.typehandling.GenericMap` object of the type to be tested
438  contents : `Mapping`
439  The key-value pairs to insert into the map
440  msg : `str`
441  Error message suffix describing test parameters
442  """
443  genericMap = mapFactory()
444 
445  for length, (key, value) in enumerate(contents.items()):
446  loopMsg = f"{msg} Inserting {key!r}={value!r}"
447  genericMap[key] = value
448  self.assertEqual(len(genericMap), length+1, msg=loopMsg)
449  self.assertEqual(genericMap[key], value, msg=loopMsg)
450 
451  self.assertEqual(dict(genericMap), dict(contents), msg=msg)
452 
453  keyType = genericMap.dtype
454  with self.assertRaises(TypeError, msg=msg):
455  genericMap[keyType(0)] = GenericMapTestBaseClass.NotAStorable()
456 
457  wrongType = float if keyType is not float else int
458  with self.assertRaises(TypeError):
459  genericMap[wrongType(0)] = 0
460 
461  def checkSetdefault(self, mapFactory, contents, msg=""):
462  """Check that GenericMap.setdefault works correctly.
463 
464  Parameters
465  ----------
466  mapFactory : callable
467  A zero-argument callable that creates an empty
468  `lsst.afw.typehandling.GenericMap` object of the type to be tested
469  contents : `Mapping`
470  The key-value pairs to insert into the map
471  msg : `str`
472  Error message suffix describing test parameters
473  """
474  genericMap = mapFactory()
475 
476  keyType = genericMap.dtype
477  result = genericMap.setdefault(keyType(0))
478  self.assertEqual(len(genericMap), 1, msg=msg)
479  self.assertIsNone(result, msg=msg)
480  self.assertIsNone(genericMap[keyType(0)], msg=msg)
481  del genericMap[keyType(0)]
482 
483  default = "This is a default"
484  for length, (key, _) in enumerate(contents.items()):
485  loopMsg = f"{msg} Defaulting {key!r}"
486  result = genericMap.setdefault(key, default)
487  self.assertEqual(len(genericMap), length+1, msg=loopMsg)
488  self.assertEqual(result, default, msg=loopMsg)
489  self.assertEqual(genericMap[key], default, msg=loopMsg)
490 
491  self.assertEqual(genericMap.keys(), contents.keys(), msg=msg)
492 
493  with self.assertRaises(TypeError, msg=msg):
494  genericMap.setdefault(keyType(100), GenericMapTestBaseClass.NotAStorable())
495 
496  wrongType = float if keyType is not float else int
497  with self.assertRaises(TypeError):
498  genericMap.setdefault(wrongType(0), default)
499 
500  genericMap = self._fillMap_fillMap(mapFactory, contents)
501  for length, (key, value) in enumerate(contents.items()):
502  loopMsg = f"{msg} Defaulting existing {key!r}={value!r}"
503  result = genericMap.setdefault(key, default)
504  self.assertEqual(len(genericMap), len(contents), msg=loopMsg)
505  self.assertEqual(result, contents[key], msg=loopMsg)
506  self.assertEqual(genericMap[key], contents[key], msg=loopMsg)
507 
508  def checkUpdateMapping(self, mapFactory, contents, msg=""):
509  """Check bulk insertion from a mapping into a GenericMap.
510 
511  Parameters
512  ----------
513  mapFactory : callable
514  A zero-argument callable that creates an empty
515  `lsst.afw.typehandling.GenericMap` object of the type to be tested
516  contents : `Mapping`
517  The key-value pairs to insert into the map
518  msg : `str`
519  Error message suffix describing test parameters
520  """
521  genericMap = self._fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
522  self.assertLess(len(genericMap), len(contents), msg=msg)
523 
524  genericMap.update(contents)
525  self.assertEqual(dict(genericMap), dict(contents), msg=msg)
526 
527  keyType = genericMap.dtype
528  with self.assertRaises(TypeError, msg=msg):
529  genericMap.update({keyType(0): GenericMapTestBaseClass.NotAStorable()})
530 
531  wrongType = float if keyType is not float else int
532  with self.assertRaises(TypeError, msg=msg):
533  genericMap.update({wrongType(0): 0})
534 
535  def checkUpdatePairs(self, mapFactory, contents, msg=""):
536  """Check bulk insertion from an iterable of pairs into a GenericMap.
537 
538  Parameters
539  ----------
540  mapFactory : callable
541  A zero-argument callable that creates an empty
542  `lsst.afw.typehandling.GenericMap` object of the type to be tested
543  contents : `Mapping`
544  The key-value pairs to insert into the map
545  msg : `str`
546  Error message suffix describing test parameters
547  """
548  genericMap = self._fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
549  self.assertLess(len(genericMap), len(contents), msg=msg)
550 
551  genericMap.update(contents.items())
552  self.assertEqual(dict(genericMap), dict(contents), msg=msg)
553 
554  keyType = genericMap.dtype
555  with self.assertRaises(TypeError, msg=msg):
556  genericMap.update([(keyType(0), GenericMapTestBaseClass.NotAStorable())])
557 
558  wrongType = float if keyType is not float else int
559  with self.assertRaises(TypeError, msg=msg):
560  genericMap.update([(wrongType(0), 0)])
561 
562  def checkUpdateKwargs(self, mapFactory, contents, msg=""):
563  """Check bulk insertion from keywords into a GenericMap.
564 
565  Parameters
566  ----------
567  mapFactory : callable
568  A zero-argument callable that creates an empty
569  `lsst.afw.typehandling.GenericMap` object of the type to be tested
570  Must allow string keys.
571  contents : `Mapping`
572  The key-value pairs to insert into the map
573  msg : `str`
574  Error message suffix describing test parameters
575  """
576  genericMap = self._fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
577  self.assertLess(len(genericMap), len(contents), msg=msg)
578 
579  genericMap.update(**contents)
580  self.assertEqual(dict(genericMap), dict(contents), msg=msg)
581 
582  with self.assertRaises(TypeError, msg=msg):
583  genericMap.update(notAKey=GenericMapTestBaseClass.NotAStorable())
584 
585  def checkReplaceItem(self, genericMap, msg=""):
586  """Check element replacement in a GenericMap.
587 
588  Parameters
589  ----------
590  genericMap : `lsst.afw.typehandling.GenericMap`
591  The map to test. Must be empty.
592  msg : `str`
593  Error message suffix describing test parameters
594  """
595  self.assertFalse(genericMap, msg=msg)
596  keyType = genericMap.dtype
597  key = keyType(42)
598 
599  for value in self.getTestDatagetTestData(keyType).values():
600  loopMsg = f"{msg} Inserting {key!r}={value!r}"
601  genericMap[key] = value # value may be of a different type
602  self.assertEqual(len(genericMap), 1, msg=loopMsg)
603  self.assertEqual(genericMap[key], value, msg=loopMsg)
604 
605  self.assertEqual(dict(genericMap), {key: value}, msg=msg)
606 
607  with self.assertRaises(TypeError, msg=msg):
608  genericMap[key] = GenericMapTestBaseClass.NotAStorable()
609 
610  def checkRemoveItem(self, mapFactory, contents, msg=""):
611  """Check element removal from a GenericMap.
612 
613  Parameters
614  ----------
615  mapFactory : callable
616  A zero-argument callable that creates an empty
617  `lsst.afw.typehandling.GenericMap` object of the type to be tested
618  contents : `Mapping`
619  The key-value pairs initially occupying the map
620  msg : `str`
621  Error message suffix describing test parameters
622  """
623  genericMap = self._fillMap_fillMap(mapFactory, contents)
624 
625  keyType = genericMap.dtype
626  with self.assertRaises(KeyError, msg=msg):
627  del genericMap[keyType(2019)]
628 
629  keysToRemove = list(contents.keys())
630  np.random.shuffle(keysToRemove)
631  for numPrevious, rawKey in enumerate(keysToRemove):
632  key = keyType(rawKey)
633  loopMsg = f"{msg} Deleting {key!r}"
634  del genericMap[key]
635  self.assertEqual(len(genericMap), len(contents)-numPrevious-1, msg=loopMsg)
636  self.assertNotIn(key, genericMap, msg=loopMsg)
637 
638  wrongType = float if keyType is not float else int
639  with self.assertRaises(TypeError):
640  del genericMap[wrongType(0)]
641 
642  def checkPop(self, mapFactory, contents, msg=""):
643  """Check that GenericMap.pop works correctly.
644 
645  Parameters
646  ----------
647  mapFactory : callable
648  A zero-argument callable that creates an empty
649  `lsst.afw.typehandling.GenericMap` object of the type to be tested
650  contents : `Mapping`
651  The key-value pairs initially occupying the map
652  msg : `str`
653  Error message suffix describing test parameters
654  """
655  genericMap = self._fillMap_fillMap(mapFactory, contents)
656 
657  keyType = genericMap.dtype
658  with self.assertRaises(KeyError, msg=msg):
659  genericMap.pop(keyType(2019))
660 
661  default = "This is a default"
662  result = genericMap.pop(keyType(2019), default)
663  self.assertEqual(dict(genericMap), dict(contents), msg=msg)
664  self.assertEqual(result, default)
665 
666  wrongType = float if keyType is not float else int
667  with self.assertRaises(TypeError):
668  genericMap.pop(wrongType(0))
669 
670  itemsToRemove = list(contents.items())
671  np.random.shuffle(itemsToRemove)
672  for numPrevious, (rawKey, value) in enumerate(itemsToRemove):
673  key = keyType(rawKey)
674  loopMsg = f"{msg} Popping {key}={value}"
675  result = genericMap.pop(key)
676  self.assertEqual(len(genericMap), len(contents)-numPrevious-1, msg=loopMsg)
677  self.assertNotIn(key, genericMap, msg=loopMsg)
678  self.assertEqual(result, value, msg=loopMsg)
679 
680  def checkPopitem(self, mapFactory, contents, msg=""):
681  """Check that GenericMap.popitem works correctly.
682 
683  Parameters
684  ----------
685  mapFactory : callable
686  A zero-argument callable that creates an empty
687  `lsst.afw.typehandling.GenericMap` object of the type to be tested
688  contents : `Mapping`
689  The key-value pairs initially occupying the map
690  msg : `str`
691  Error message suffix describing test parameters
692  """
693  genericMap = self._fillMap_fillMap(mapFactory, contents)
694 
695  for numPrevious in range(len(genericMap)):
696  key, value = genericMap.popitem()
697  loopMsg = f"{msg} Popping {key}={value}"
698  self.assertIn((key, value), contents.items(), msg=loopMsg)
699  self.assertEqual(len(genericMap), len(contents)-numPrevious-1, msg=loopMsg)
700  self.assertNotIn(key, genericMap, msg=loopMsg)
701 
702  with self.assertRaises(KeyError, msg=msg):
703  genericMap.popitem()
704 
705  def checkClear(self, mapFactory, contents, msg=""):
706  """Check erasing a GenericMap.
707 
708  Parameters
709  ----------
710  mapFactory : callable
711  A zero-argument callable that creates an empty
712  `lsst.afw.typehandling.GenericMap` object of the type to be tested
713  contents : `Mapping`
714  The key-value pairs initially occupying the map
715  msg : `str`
716  Error message suffix describing test parameters
717  """
718  genericMap = self._fillMap_fillMap(mapFactory, contents)
719  self.assertTrue(genericMap, msg=msg)
720 
721  genericMap.clear()
722  self.assertFalse(genericMap, msg=msg)
723  self.assertEqual(len(genericMap), 0, msg=msg)
724  for key in genericMap:
725  self.fail(f"Unexpected key: {key}", msg=msg)
726 
727  def checkMutableViews(self, mapFactory, contents, msg=""):
728  """Check that the views of a GenericMap update automatically.
729 
730  This test supersedes `GenericMapTestBaseClass.checkViews`.
731 
732  Parameters
733  ----------
734  genericMap : `lsst.afw.typehandling.GenericMap`
735  The map to test.
736  contents : `Mapping`
737  The key-value pairs that should be present in ``genericMap``
738  msg : `str`
739  Error message suffix describing test parameters
740  """
741  genericMap = mapFactory()
742  keyView = genericMap.keys()
743  valueView = genericMap.values()
744  itemView = genericMap.items()
745 
746  for view in (keyView, valueView, itemView):
747  self.assertEqual(len(view), len(genericMap), msg=msg)
748  # is initial state correct?
749  self.checkViewscheckViews(genericMap, {}, msg)
750 
751  for key, value in contents.items():
752  genericMap[key] = value
753 
754  for view in (keyView, valueView, itemView):
755  self.assertEqual(len(view), len(genericMap), msg=msg)
756  # is final state correct?
757  self.checkViewscheckViews(genericMap, contents, msg)
std::vector< SchemaItem< Flag > > * items
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:58
def checkViews(self, genericMap, contents, msg="")
Definition: testUtils.py:350
def checkFromKeysDefault(self, mapClass, keys, msg="")
Definition: testUtils.py:224
def checkInitPairs(self, mapClass, contents, msg="")
Definition: testUtils.py:179
def checkGet(self, genericMap, contents, msg="")
Definition: testUtils.py:310
def checkContains(self, genericMap, contents, msg="")
Definition: testUtils.py:262
def checkInitKwargs(self, mapClass, contents, msg="")
Definition: testUtils.py:205
def checkIteration(self, genericMap, contents, msg="")
Definition: testUtils.py:336
def checkInitMapping(self, mapClass, contents, msg="")
Definition: testUtils.py:153
def checkFromKeys(self, mapClass, keys, value, msg="")
Definition: testUtils.py:244
def checkContents(self, genericMap, contents, msg="")
Definition: testUtils.py:286
def checkMutableViews(self, mapFactory, contents, msg="")
Definition: testUtils.py:727
def checkPop(self, mapFactory, contents, msg="")
Definition: testUtils.py:642
def checkUpdateKwargs(self, mapFactory, contents, msg="")
Definition: testUtils.py:562
def checkClear(self, mapFactory, contents, msg="")
Definition: testUtils.py:705
def checkInsertItem(self, mapFactory, contents, msg="")
Definition: testUtils.py:430
def checkUpdatePairs(self, mapFactory, contents, msg="")
Definition: testUtils.py:535
def checkRemoveItem(self, mapFactory, contents, msg="")
Definition: testUtils.py:610
def checkSetdefault(self, mapFactory, contents, msg="")
Definition: testUtils.py:461
def checkPopitem(self, mapFactory, contents, msg="")
Definition: testUtils.py:680
def _fillPartialMap(cls, mapFactory, contents, numElements)
Definition: testUtils.py:394
def checkUpdateMapping(self, mapFactory, contents, msg="")
Definition: testUtils.py:508
daf::base::PropertyList * list
Definition: fits.cc:913
daf::base::PropertySet * set
Definition: fits.cc:912