LSSTApplications  19.0.0-10-g920eed2,19.0.0-11-g48a0200+2,19.0.0-18-gfc4e62b+17,19.0.0-2-g3b2f90d+2,19.0.0-2-gd671419+5,19.0.0-20-g5a5a17ab+15,19.0.0-21-g2644856+18,19.0.0-23-g84eeccb+6,19.0.0-24-g878c510+5,19.0.0-25-g6c8df7140,19.0.0-25-gb330496+5,19.0.0-3-g2b32d65+5,19.0.0-3-g8227491+16,19.0.0-3-g9c54d0d+16,19.0.0-3-gca68e65+12,19.0.0-3-gcfc5f51+5,19.0.0-3-ge110943+15,19.0.0-3-ge74d124,19.0.0-3-gfe04aa6+16,19.0.0-30-g9c3fd16+6,19.0.0-4-g06f5963+5,19.0.0-4-g3d16501+18,19.0.0-4-g4a9c019+5,19.0.0-4-g5a8b323,19.0.0-4-g66397f0+1,19.0.0-4-g8278b9b+1,19.0.0-4-g8557e14,19.0.0-4-g8964aba+17,19.0.0-4-ge404a01+16,19.0.0-5-g40f3a5a,19.0.0-5-g4db63b3,19.0.0-5-gfb03ce7+17,19.0.0-6-gbaebbfb+16,19.0.0-61-gec4c6e08+6,19.0.0-7-g039c0b5+16,19.0.0-7-gbea9075+4,19.0.0-7-gc567de5+17,19.0.0-70-g334bf3e+1,19.0.0-9-g463f923+16,b.20.0.x-g5487ab2134,v20.0.0.rc1
LSSTDataManagementBasePackage
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 
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__ == other.__class__
57 
59  """A subclass of Storable for testing purposes.
60  """
61  def __init__(self, storage):
62  super().__init__()
63  self._storage = storage
64 
65  def __repr__(self):
66  return f"ComplexStorable({self._storage!r})"
67 
68  def __hash__(self):
69  return hash(self._storage)
70 
71  def __eq__(self, other):
72  """Warning: violates both substitution and equality symmetry!
73  """
74  if self.__class__ == other.__class__:
75  return self._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.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.longMessage = 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.getValidKeys(mapClass):
166  genericMap = mapClass(contents)
167  self.checkContents(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.checkContents(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.getValidKeys(mapClass):
192  genericMap = mapClass(contents.items())
193  self.checkContents(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.checkContents(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.checkContents(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.checkContents(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.checkContents(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(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(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(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(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(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.getTestData(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(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(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(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(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.checkViews(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.checkViews(genericMap, contents, msg)
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.SimpleStorable.__eq__
def __eq__(self, other)
Definition: testUtils.py:53
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass
Definition: testUtils.py:367
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkInitPairs
def checkInitPairs(self, mapClass, contents, msg="")
Definition: testUtils.py:179
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.SimpleStorable.__repr__
def __repr__(self)
Definition: testUtils.py:47
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkContains
def checkContains(self, genericMap, contents, msg="")
Definition: testUtils.py:262
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.longMessage
longMessage
Definition: testUtils.py:136
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.SimpleStorable.__class__
__class__
Definition: testUtils.py:56
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass._fillPartialMap
def _fillPartialMap(cls, mapFactory, contents, numElements)
Definition: testUtils.py:394
lsst::afw::typehandling::Storable
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:58
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkInitMapping
def checkInitMapping(self, mapClass, contents, msg="")
Definition: testUtils.py:153
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkGet
def checkGet(self, genericMap, contents, msg="")
Definition: testUtils.py:310
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable.__init__
def __init__(self, storage)
Definition: testUtils.py:61
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.NotAStorable
Definition: testUtils.py:79
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.getTestData
def getTestData(cls, keyClass)
Definition: testUtils.py:96
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkViews
def checkViews(self, genericMap, contents, msg="")
Definition: testUtils.py:350
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.getValidKeys
def getValidKeys(mapClass)
Definition: testUtils.py:107
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkFromKeys
def checkFromKeys(self, mapClass, keys, value, msg="")
Definition: testUtils.py:244
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkFromKeysDefault
def checkFromKeysDefault(self, mapClass, keys, msg="")
Definition: testUtils.py:224
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkPopitem
def checkPopitem(self, mapFactory, contents, msg="")
Definition: testUtils.py:680
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass
Definition: testUtils.py:33
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkUpdatePairs
def checkUpdatePairs(self, mapFactory, contents, msg="")
Definition: testUtils.py:535
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkReplaceItem
def checkReplaceItem(self, genericMap, msg="")
Definition: testUtils.py:585
lsst::utils.tests.TestCase
Definition: tests.py:408
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass._testData
_testData
Definition: testUtils.py:85
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable._storage
_storage
Definition: testUtils.py:63
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkContents
def checkContents(self, genericMap, contents, msg="")
Definition: testUtils.py:286
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable.__hash__
def __hash__(self)
Definition: testUtils.py:68
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkClear
def checkClear(self, mapFactory, contents, msg="")
Definition: testUtils.py:705
lsst::afw::typehandling
Definition: type_traits.h:32
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable
Definition: testUtils.py:58
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkRemoveItem
def checkRemoveItem(self, mapFactory, contents, msg="")
Definition: testUtils.py:610
lsst::utils.tests
Definition: tests.py:1
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass._fillMap
def _fillMap(cls, mapFactory, contents)
Definition: testUtils.py:375
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkUpdateMapping
def checkUpdateMapping(self, mapFactory, contents, msg="")
Definition: testUtils.py:508
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkPop
def checkPop(self, mapFactory, contents, msg="")
Definition: testUtils.py:642
items
std::vector< SchemaItem< Flag > > * items
Definition: BaseColumnView.cc:142
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.setUp
def setUp(self)
Definition: testUtils.py:128
list
daf::base::PropertyList * list
Definition: fits.cc:913
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkSetdefault
def checkSetdefault(self, mapFactory, contents, msg="")
Definition: testUtils.py:461
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkMutableViews
def checkMutableViews(self, mapFactory, contents, msg="")
Definition: testUtils.py:727
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable.__repr__
def __repr__(self)
Definition: testUtils.py:65
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkUpdateKwargs
def checkUpdateKwargs(self, mapFactory, contents, msg="")
Definition: testUtils.py:562
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkInitKwargs
def checkInitKwargs(self, mapClass, contents, msg="")
Definition: testUtils.py:205
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.NotAStorable.__str__
def __str__(self)
Definition: testUtils.py:82
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.SimpleStorable
Definition: testUtils.py:44
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.SimpleStorable.__hash__
def __hash__(self)
Definition: testUtils.py:50
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.checkIteration
def checkIteration(self, genericMap, contents, msg="")
Definition: testUtils.py:336
set
daf::base::PropertySet * set
Definition: fits.cc:912
lsst::afw::typehandling.testUtils.GenericMapTestBaseClass.ComplexStorable.__eq__
def __eq__(self, other)
Definition: testUtils.py:71
lsst::afw::typehandling.testUtils.MutableGenericMapTestBaseClass.checkInsertItem
def checkInsertItem(self, mapFactory, contents, msg="")
Definition: testUtils.py:430