|
11 | 11 | import re |
12 | 12 | import sys |
13 | 13 | from collections import UserDict |
| 14 | +from collections import _ChainMap as ChainMap |
14 | 15 | from collections.abc import Hashable, Iterable, Iterator |
15 | 16 | from collections.abc import Sized, Container, Callable |
16 | 17 | from collections.abc import Set, MutableSet |
17 | 18 | from collections.abc import Mapping, MutableMapping, KeysView, ItemsView |
18 | 19 | from collections.abc import Sequence, MutableSequence |
19 | 20 | from collections.abc import ByteString |
20 | 21 |
|
| 22 | + |
| 23 | +################################################################################ |
| 24 | +### _ChainMap (helper class for configparser and the string module) |
| 25 | +################################################################################ |
| 26 | + |
| 27 | +class TestChainMap(unittest.TestCase): |
| 28 | + |
| 29 | + def test_basics(self): |
| 30 | + c = ChainMap() |
| 31 | + c['a'] = 1 |
| 32 | + c['b'] = 2 |
| 33 | + d = c.new_child() |
| 34 | + d['b'] = 20 |
| 35 | + d['c'] = 30 |
| 36 | + self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state |
| 37 | + self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem |
| 38 | + self.assertEqual(len(d), 3) # check len |
| 39 | + for key in 'abc': # check contains |
| 40 | + self.assertIn(key, d) |
| 41 | + for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get |
| 42 | + self.assertEqual(d.get(k, 100), v) |
| 43 | + |
| 44 | + del d['b'] # unmask a value |
| 45 | + self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state |
| 46 | + self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem |
| 47 | + self.assertEqual(len(d), 3) # check len |
| 48 | + for key in 'abc': # check contains |
| 49 | + self.assertIn(key, d) |
| 50 | + for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get |
| 51 | + self.assertEqual(d.get(k, 100), v) |
| 52 | + self.assertIn(repr(d), [ # check repr |
| 53 | + type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})", |
| 54 | + type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})" |
| 55 | + ]) |
| 56 | + |
| 57 | + for e in d.copy(), copy.copy(d): # check shallow copies |
| 58 | + self.assertEqual(d, e) |
| 59 | + self.assertEqual(d.maps, e.maps) |
| 60 | + self.assertIsNot(d, e) |
| 61 | + self.assertIsNot(d.maps[0], e.maps[0]) |
| 62 | + for m1, m2 in zip(d.maps[1:], e.maps[1:]): |
| 63 | + self.assertIs(m1, m2) |
| 64 | + |
| 65 | + for e in [pickle.loads(pickle.dumps(d)), |
| 66 | + copy.deepcopy(d), |
| 67 | + eval(repr(d)) |
| 68 | + ]: # check deep copies |
| 69 | + self.assertEqual(d, e) |
| 70 | + self.assertEqual(d.maps, e.maps) |
| 71 | + self.assertIsNot(d, e) |
| 72 | + for m1, m2 in zip(d.maps, e.maps): |
| 73 | + self.assertIsNot(m1, m2, e) |
| 74 | + |
| 75 | + d.new_child() |
| 76 | + d['b'] = 5 |
| 77 | + self.assertEqual(d.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}]) |
| 78 | + self.assertEqual(d.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents |
| 79 | + self.assertEqual(d['b'], 5) # find first in chain |
| 80 | + self.assertEqual(d.parents['b'], 2) # look beyond maps[0] |
| 81 | + |
| 82 | + def test_contructor(self): |
| 83 | + self.assertEqual(ChainedContext().maps, [{}]) # no-args --> one new dict |
| 84 | + self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list |
| 85 | + |
| 86 | + def test_missing(self): |
| 87 | + class DefaultChainMap(ChainMap): |
| 88 | + def __missing__(self, key): |
| 89 | + return 999 |
| 90 | + d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30)) |
| 91 | + for k, v in dict(a=1, b=2, c=30, d=999).items(): |
| 92 | + self.assertEqual(d[k], v) # check __getitem__ w/missing |
| 93 | + for k, v in dict(a=1, b=2, c=30, d=77).items(): |
| 94 | + self.assertEqual(d.get(k, 77), v) # check get() w/ missing |
| 95 | + for k, v in dict(a=True, b=True, c=True, d=False).items(): |
| 96 | + self.assertEqual(k in d, v) # check __contains__ w/missing |
| 97 | + self.assertEqual(d.pop('a', 1001), 1, d) |
| 98 | + self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing |
| 99 | + self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing |
| 100 | + with self.assertRaises(KeyError): |
| 101 | + d.popitem() |
| 102 | + |
| 103 | + def test_dict_coercion(self): |
| 104 | + d = ChainMap(dict(a=1, b=2), dict(b=20, c=30)) |
| 105 | + self.assertEqual(dict(d), dict(a=1, b=2, c=30)) |
| 106 | + self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30)) |
| 107 | + |
| 108 | + |
| 109 | +################################################################################ |
| 110 | +### Named Tuples |
| 111 | +################################################################################ |
| 112 | + |
21 | 113 | TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests |
22 | 114 |
|
23 | 115 | class TestNamedTuple(unittest.TestCase): |
@@ -229,6 +321,10 @@ class B(A): |
229 | 321 | self.assertEqual(repr(B(1)), 'B(x=1)') |
230 | 322 |
|
231 | 323 |
|
| 324 | +################################################################################ |
| 325 | +### Abstract Base Classes |
| 326 | +################################################################################ |
| 327 | + |
232 | 328 | class ABCTestCase(unittest.TestCase): |
233 | 329 |
|
234 | 330 | def validate_abstract_methods(self, abc, *names): |
@@ -626,6 +722,11 @@ def test_MutableSequence(self): |
626 | 722 | self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__', |
627 | 723 | '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') |
628 | 724 |
|
| 725 | + |
| 726 | +################################################################################ |
| 727 | +### Counter |
| 728 | +################################################################################ |
| 729 | + |
629 | 730 | class TestCounter(unittest.TestCase): |
630 | 731 |
|
631 | 732 | def test_basics(self): |
@@ -789,6 +890,11 @@ def test_helper_function(self): |
789 | 890 | self.assertEqual(m, |
790 | 891 | OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])) |
791 | 892 |
|
| 893 | + |
| 894 | +################################################################################ |
| 895 | +### OrderedDict |
| 896 | +################################################################################ |
| 897 | + |
792 | 898 | class TestOrderedDict(unittest.TestCase): |
793 | 899 |
|
794 | 900 | def test_init(self): |
@@ -1067,6 +1173,10 @@ def test_popitem(self): |
1067 | 1173 | self.assertRaises(KeyError, d.popitem) |
1068 | 1174 |
|
1069 | 1175 |
|
| 1176 | +################################################################################ |
| 1177 | +### Run tests |
| 1178 | +################################################################################ |
| 1179 | + |
1070 | 1180 | import doctest, collections |
1071 | 1181 |
|
1072 | 1182 | def test_main(verbose=None): |
|
0 commit comments