Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 499e193

Browse files
committed
Add tests for the _ChainMap helper class.
1 parent 08f5cf5 commit 499e193

2 files changed

Lines changed: 119 additions & 0 deletions

File tree

Lib/collections/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,15 @@ def copy(self):
695695

696696
__copy__ = copy
697697

698+
def new_child(self): # like Django's Context.push()
699+
'New ChainMap with a new dict followed by all previous maps.'
700+
return self.__class__({}, *self.maps)
701+
702+
@property
703+
def parents(self): # like Django's Context.pop()
704+
'New ChainMap from maps[1:].'
705+
return self.__class__(*self.maps[1:])
706+
698707
def __setitem__(self, key, value):
699708
self.maps[0][key] = value
700709

Lib/test/test_collections.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,105 @@
1111
import re
1212
import sys
1313
from collections import UserDict
14+
from collections import _ChainMap as ChainMap
1415
from collections.abc import Hashable, Iterable, Iterator
1516
from collections.abc import Sized, Container, Callable
1617
from collections.abc import Set, MutableSet
1718
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
1819
from collections.abc import Sequence, MutableSequence
1920
from collections.abc import ByteString
2021

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+
21113
TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
22114

23115
class TestNamedTuple(unittest.TestCase):
@@ -229,6 +321,10 @@ class B(A):
229321
self.assertEqual(repr(B(1)), 'B(x=1)')
230322

231323

324+
################################################################################
325+
### Abstract Base Classes
326+
################################################################################
327+
232328
class ABCTestCase(unittest.TestCase):
233329

234330
def validate_abstract_methods(self, abc, *names):
@@ -626,6 +722,11 @@ def test_MutableSequence(self):
626722
self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
627723
'__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
628724

725+
726+
################################################################################
727+
### Counter
728+
################################################################################
729+
629730
class TestCounter(unittest.TestCase):
630731

631732
def test_basics(self):
@@ -789,6 +890,11 @@ def test_helper_function(self):
789890
self.assertEqual(m,
790891
OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
791892

893+
894+
################################################################################
895+
### OrderedDict
896+
################################################################################
897+
792898
class TestOrderedDict(unittest.TestCase):
793899

794900
def test_init(self):
@@ -1067,6 +1173,10 @@ def test_popitem(self):
10671173
self.assertRaises(KeyError, d.popitem)
10681174

10691175

1176+
################################################################################
1177+
### Run tests
1178+
################################################################################
1179+
10701180
import doctest, collections
10711181

10721182
def test_main(verbose=None):

0 commit comments

Comments
 (0)