24 from collections
import Counter
34 """Base class for unit tests of GenericMap.
36 Subclasses must call `GenericMapTestBaseClass.setUp(self)`
37 if they provide their own version.
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
45 """A subclass of Storable for testing purposes.
48 return "Simplest possible representation"
54 """Warning: violates both substitution and equality symmetry!
56 return self.
__class____class__ == other.__class__
59 """A subclass of Storable for testing purposes.
66 return f
"ComplexStorable({self._storage!r})"
72 """Warning: violates both substitution and equality symmetry!
75 return self.
_storage_storage == other._storage
80 """A class that should not be a legal value in a GenericMap.
89 3:
"How many roads must a man walk down?",
97 """Generic dataset for testing GenericMap classes that can handle it.
102 The type of key expected by the GenericMap.
104 return {keyClass(key): value
for key, value
in cls.
_testData_testData.
items()}
108 """Return all keys suitable for a GenericMap.
113 A type object for a subclass of either `GenericMap` or a
114 key-specific specialization.
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
124 return {mapClass.dtype}
125 except AttributeError:
126 return {cls.dtype
for cls
in mapClass.__subclasses__()}
131 Subclasses must call this method if they override setUp.
154 """Check initialization from a mapping.
158 mapClass : `lsst.afw.typehandling.GenericMap`-type
159 The class whose ``__init__`` method will be tested.
161 The key-value pairs to insert into the map
163 Error message suffix describing test parameters
166 genericMap = mapClass(contents)
167 self.
checkContentscheckContents(genericMap, contents, msg=msg)
169 extraContents = {key: value
for key, value
in contents.items()}
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)
176 with self.assertRaises(TypeError, msg=msg):
180 """Check initialization from an iterable of pairs.
184 mapClass: `lsst.afw.typehandling.GenericMap`-type
185 The class whose ``__init__`` method will be tested.
187 The key-value pairs to insert into the map
189 Error message suffix describing test parameters
192 genericMap = mapClass(contents.items())
193 self.
checkContentscheckContents(genericMap, contents, msg=msg)
195 extraContents = {key: value
for key, value
in contents.items()}
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)
202 with self.assertRaises(TypeError, msg=msg):
206 """Check bulk insertion from keywords into a GenericMap.
210 mapClass: `lsst.afw.typehandling.GenericMapS`-type
211 The class whose ``__init__`` method will be tested.
212 Must allow string keys.
214 The key-value pairs to insert into the map
216 Error message suffix describing test parameters
218 genericMap = mapClass(**contents)
219 self.
checkContentscheckContents(genericMap, contents, msg=msg)
221 with self.assertRaises(TypeError, msg=msg):
225 """Check initialization using the ``fromkeys`` factory.
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`).
233 mapClass: `lsst.afw.typehandling.GenericMap`-type
234 The class whose ``fromkeys`` method will be tested.
236 The keys to insert into the map.
238 Error message suffix describing test parameters
240 genericMap = mapClass.fromkeys(keys)
241 self.assertIsInstance(genericMap, mapClass, msg=msg)
242 self.
checkContentscheckContents(genericMap, dict.fromkeys(keys), msg=msg)
245 """Check initialization using the ``fromkeys`` factory.
249 mapClass: `lsst.afw.typehandling.GenericMap`-type
250 The class whose ``fromkeys`` method will be tested.
252 The keys to insert into the map.
254 A legal value for a GenericMap.
256 Error message suffix describing test parameters
258 genericMap = mapClass.fromkeys(keys, value)
259 self.assertIsInstance(genericMap, mapClass, msg=msg)
260 self.
checkContentscheckContents(genericMap, dict.fromkeys(keys, value), msg=msg)
263 """Check the contents of a GenericMap.
267 genericMap : `lsst.afw.typehandling.GenericMap`
270 The key-value pairs that should be present in ``genericMap``
272 Error message suffix describing test parameters
275 self.assertIn(key, genericMap, msg=msg)
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)
282 wrongType = float
if keyType
is not float
else int
283 with self.assertRaises(TypeError):
284 wrongType(0)
in genericMap
287 """Check the contents of a GenericMap.
291 genericMap : `lsst.afw.typehandling.GenericMap`
294 The key-value pairs that should be present in ``genericMap``
296 Error message suffix describing test parameters
298 for key, value
in contents.items():
299 self.assertEqual(genericMap[key], value, msg=msg)
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):
306 wrongType = float
if keyType
is not float
else int
307 with self.assertRaises(TypeError):
308 genericMap[wrongType(0)]
311 """Check that GenericMap.get works correctly.
315 genericMap : `lsst.afw.typehandling.GenericMap`
318 The key-value pairs that should be present in ``genericMap``
320 Error message suffix describing test parameters
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)
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)
332 wrongType = float
if keyType
is not float
else int
333 with self.assertRaises(TypeError):
334 genericMap.get(wrongType(0))
337 """Check the result of iterating over a GenericMap.
341 genericMap : `lsst.afw.typehandling.GenericMap`
344 The key-value pairs that should be present in ``genericMap``
346 Error message suffix describing test parameters
348 self.assertEqual({key: genericMap[key]
for key
in genericMap}, dict(contents), msg=msg)
351 """Check the views provided by a GenericMap.
355 genericMap : `lsst.afw.typehandling.GenericMap`
358 The key-value pairs that should be present in ``genericMap``
360 Error message suffix describing test parameters
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)
368 """Base class for unit tests of GenericMap that allow insertion/deletion.
370 Subclasses must call `MutableGenericMapTestBaseClass.setUp(self)`
371 if they provide their own version.
375 def _fillMap(cls, mapFactory, contents):
376 """Create a new GenericMap with particular contents.
380 mapFactory : callable
381 A zero-argument callable that creates an empty
382 `lsst.afw.typehandling.GenericMap` object
384 The key-value pairs that should be present in the new map.
388 map : `lsst.afw.typehandling.GenericMap`
389 a GenericMap equivalent to ``contents``
391 return cls.
_fillPartialMap_fillPartialMap(mapFactory, contents, len(contents))
394 def _fillPartialMap(cls, mapFactory, contents, numElements):
395 """Create a new GenericMap with particular contents.
399 mapFactory : callable
400 A zero-argument callable that creates an empty
401 `lsst.afw.typehandling.GenericMap` object
403 The key-value pairs that should be present in the new map.
405 The number of elements from ``contents`` to be inserted.
409 map : `lsst.afw.typehandling.GenericMap`
410 a GenericMap containing ``numElements`` of ``contents`` or all of
411 ``contents``, whichever is smaller
413 newMap = mapFactory()
414 for i, (key, value)
in enumerate(contents.items()):
431 """Check element insertion in a GenericMap.
435 mapFactory : callable
436 A zero-argument callable that creates an empty
437 `lsst.afw.typehandling.GenericMap` object of the type to be tested
439 The key-value pairs to insert into the map
441 Error message suffix describing test parameters
443 genericMap = mapFactory()
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)
451 self.assertEqual(dict(genericMap), dict(contents), msg=msg)
453 keyType = genericMap.dtype
454 with self.assertRaises(TypeError, msg=msg):
457 wrongType = float
if keyType
is not float
else int
458 with self.assertRaises(TypeError):
459 genericMap[wrongType(0)] = 0
462 """Check that GenericMap.setdefault works correctly.
466 mapFactory : callable
467 A zero-argument callable that creates an empty
468 `lsst.afw.typehandling.GenericMap` object of the type to be tested
470 The key-value pairs to insert into the map
472 Error message suffix describing test parameters
474 genericMap = mapFactory()
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)]
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)
491 self.assertEqual(genericMap.keys(), contents.keys(), msg=msg)
493 with self.assertRaises(TypeError, msg=msg):
496 wrongType = float
if keyType
is not float
else int
497 with self.assertRaises(TypeError):
498 genericMap.setdefault(wrongType(0), default)
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)
509 """Check bulk insertion from a mapping into a GenericMap.
513 mapFactory : callable
514 A zero-argument callable that creates an empty
515 `lsst.afw.typehandling.GenericMap` object of the type to be tested
517 The key-value pairs to insert into the map
519 Error message suffix describing test parameters
521 genericMap = self.
_fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
522 self.assertLess(len(genericMap), len(contents), msg=msg)
524 genericMap.update(contents)
525 self.assertEqual(dict(genericMap), dict(contents), msg=msg)
527 keyType = genericMap.dtype
528 with self.assertRaises(TypeError, msg=msg):
531 wrongType = float
if keyType
is not float
else int
532 with self.assertRaises(TypeError, msg=msg):
533 genericMap.update({wrongType(0): 0})
536 """Check bulk insertion from an iterable of pairs into a GenericMap.
540 mapFactory : callable
541 A zero-argument callable that creates an empty
542 `lsst.afw.typehandling.GenericMap` object of the type to be tested
544 The key-value pairs to insert into the map
546 Error message suffix describing test parameters
548 genericMap = self.
_fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
549 self.assertLess(len(genericMap), len(contents), msg=msg)
551 genericMap.update(contents.items())
552 self.assertEqual(dict(genericMap), dict(contents), msg=msg)
554 keyType = genericMap.dtype
555 with self.assertRaises(TypeError, msg=msg):
558 wrongType = float
if keyType
is not float
else int
559 with self.assertRaises(TypeError, msg=msg):
560 genericMap.update([(wrongType(0), 0)])
563 """Check bulk insertion from keywords into a GenericMap.
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.
572 The key-value pairs to insert into the map
574 Error message suffix describing test parameters
576 genericMap = self.
_fillPartialMap_fillPartialMap(mapFactory, dict.fromkeys(contents, 0), len(contents)/2)
577 self.assertLess(len(genericMap), len(contents), msg=msg)
579 genericMap.update(**contents)
580 self.assertEqual(dict(genericMap), dict(contents), msg=msg)
582 with self.assertRaises(TypeError, msg=msg):
586 """Check element replacement in a GenericMap.
590 genericMap : `lsst.afw.typehandling.GenericMap`
591 The map to test. Must be empty.
593 Error message suffix describing test parameters
595 self.assertFalse(genericMap, msg=msg)
596 keyType = genericMap.dtype
599 for value
in self.
getTestDatagetTestData(keyType).values():
600 loopMsg = f
"{msg} Inserting {key!r}={value!r}"
601 genericMap[key] = value
602 self.assertEqual(len(genericMap), 1, msg=loopMsg)
603 self.assertEqual(genericMap[key], value, msg=loopMsg)
605 self.assertEqual(dict(genericMap), {key: value}, msg=msg)
607 with self.assertRaises(TypeError, msg=msg):
611 """Check element removal from a GenericMap.
615 mapFactory : callable
616 A zero-argument callable that creates an empty
617 `lsst.afw.typehandling.GenericMap` object of the type to be tested
619 The key-value pairs initially occupying the map
621 Error message suffix describing test parameters
623 genericMap = self.
_fillMap_fillMap(mapFactory, contents)
625 keyType = genericMap.dtype
626 with self.assertRaises(KeyError, msg=msg):
627 del genericMap[keyType(2019)]
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}"
635 self.assertEqual(len(genericMap), len(contents)-numPrevious-1, msg=loopMsg)
636 self.assertNotIn(key, genericMap, msg=loopMsg)
638 wrongType = float
if keyType
is not float
else int
639 with self.assertRaises(TypeError):
640 del genericMap[wrongType(0)]
643 """Check that GenericMap.pop works correctly.
647 mapFactory : callable
648 A zero-argument callable that creates an empty
649 `lsst.afw.typehandling.GenericMap` object of the type to be tested
651 The key-value pairs initially occupying the map
653 Error message suffix describing test parameters
655 genericMap = self.
_fillMap_fillMap(mapFactory, contents)
657 keyType = genericMap.dtype
658 with self.assertRaises(KeyError, msg=msg):
659 genericMap.pop(keyType(2019))
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)
666 wrongType = float
if keyType
is not float
else int
667 with self.assertRaises(TypeError):
668 genericMap.pop(wrongType(0))
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)
681 """Check that GenericMap.popitem works correctly.
685 mapFactory : callable
686 A zero-argument callable that creates an empty
687 `lsst.afw.typehandling.GenericMap` object of the type to be tested
689 The key-value pairs initially occupying the map
691 Error message suffix describing test parameters
693 genericMap = self.
_fillMap_fillMap(mapFactory, contents)
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)
702 with self.assertRaises(KeyError, msg=msg):
706 """Check erasing a GenericMap.
710 mapFactory : callable
711 A zero-argument callable that creates an empty
712 `lsst.afw.typehandling.GenericMap` object of the type to be tested
714 The key-value pairs initially occupying the map
716 Error message suffix describing test parameters
718 genericMap = self.
_fillMap_fillMap(mapFactory, contents)
719 self.assertTrue(genericMap, msg=msg)
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)
728 """Check that the views of a GenericMap update automatically.
730 This test supersedes `GenericMapTestBaseClass.checkViews`.
734 genericMap : `lsst.afw.typehandling.GenericMap`
737 The key-value pairs that should be present in ``genericMap``
739 Error message suffix describing test parameters
741 genericMap = mapFactory()
742 keyView = genericMap.keys()
743 valueView = genericMap.values()
744 itemView = genericMap.items()
746 for view
in (keyView, valueView, itemView):
747 self.assertEqual(len(view), len(genericMap), msg=msg)
749 self.
checkViewscheckViews(genericMap, {}, msg)
751 for key, value
in contents.items():
752 genericMap[key] = value
754 for view
in (keyView, valueView, itemView):
755 self.assertEqual(len(view), len(genericMap), msg=msg)
757 self.
checkViewscheckViews(genericMap, contents, msg)
std::vector< SchemaItem< Flag > > * items
Interface supporting iteration over heterogenous containers.
def __init__(self, storage)
def getTestData(cls, keyClass)
def checkViews(self, genericMap, contents, msg="")
def checkFromKeysDefault(self, mapClass, keys, msg="")
def getValidKeys(mapClass)
def checkInitPairs(self, mapClass, contents, msg="")
def checkGet(self, genericMap, contents, msg="")
def checkContains(self, genericMap, contents, msg="")
def checkInitKwargs(self, mapClass, contents, msg="")
def checkIteration(self, genericMap, contents, msg="")
def checkInitMapping(self, mapClass, contents, msg="")
def checkFromKeys(self, mapClass, keys, value, msg="")
def checkContents(self, genericMap, contents, msg="")
def checkMutableViews(self, mapFactory, contents, msg="")
def checkPop(self, mapFactory, contents, msg="")
def checkUpdateKwargs(self, mapFactory, contents, msg="")
def checkClear(self, mapFactory, contents, msg="")
def checkInsertItem(self, mapFactory, contents, msg="")
def checkUpdatePairs(self, mapFactory, contents, msg="")
def checkRemoveItem(self, mapFactory, contents, msg="")
def checkSetdefault(self, mapFactory, contents, msg="")
def checkReplaceItem(self, genericMap, msg="")
def checkPopitem(self, mapFactory, contents, msg="")
def _fillMap(cls, mapFactory, contents)
def _fillPartialMap(cls, mapFactory, contents, numElements)
def checkUpdateMapping(self, mapFactory, contents, msg="")
daf::base::PropertyList * list
daf::base::PropertySet * set