summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2013-01-11 23:39:53 (GMT)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2013-01-11 23:39:53 (GMT)
commit1ba81ee19a25d52df2d5ce193375086164b1ca77 (patch)
tree6f91d0f4827fa62e35d98c6125f2156b24f552fc /Lib
parent569ff4fbbc4cd0589c369519745d8d17bf3094b0 (diff)
downloadcpython-1ba81ee19a25d52df2d5ce193375086164b1ca77.zip
cpython-1ba81ee19a25d52df2d5ce193375086164b1ca77.tar.gz
cpython-1ba81ee19a25d52df2d5ce193375086164b1ca77.tar.bz2
Closes #16613: Added optional mapping argument to ChainMap.new_child.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/collections/__init__.py11
-rw-r--r--Lib/test/test_collections.py32
2 files changed, 40 insertions, 3 deletions
diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py
index 53083e4..0612e1f 100644
--- a/Lib/collections/__init__.py
+++ b/Lib/collections/__init__.py
@@ -821,9 +821,14 @@ class ChainMap(MutableMapping):
__copy__ = copy
- def new_child(self): # like Django's Context.push()
- 'New ChainMap with a new dict followed by all previous maps.'
- return self.__class__({}, *self.maps)
+ def new_child(self, m=None): # like Django's Context.push()
+ '''
+ New ChainMap with a new map followed by all previous maps. If no
+ map is provided, an empty dict is used.
+ '''
+ if m is None:
+ m = {}
+ return self.__class__(m, *self.maps)
@property
def parents(self): # like Django's Context.pop()
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 8850e8b..dfad78e 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -112,6 +112,38 @@ class TestChainMap(unittest.TestCase):
self.assertEqual(dict(d), dict(a=1, b=2, c=30))
self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
+ def test_new_child(self):
+ 'Tests for changes for issue #16613.'
+ c = ChainMap()
+ c['a'] = 1
+ c['b'] = 2
+ m = {'b':20, 'c': 30}
+ d = c.new_child(m)
+ self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
+ self.assertIs(m, d.maps[0])
+
+ # Use a different map than a dict
+ class lowerdict(dict):
+ def __getitem__(self, key):
+ if isinstance(key, str):
+ key = key.lower()
+ return dict.__getitem__(self, key)
+ def __contains__(self, key):
+ if isinstance(key, str):
+ key = key.lower()
+ return dict.__contains__(self, key)
+
+ c = ChainMap()
+ c['a'] = 1
+ c['b'] = 2
+ m = lowerdict(b=20, c=30)
+ d = c.new_child(m)
+ self.assertIs(m, d.maps[0])
+ for key in 'abc': # check contains
+ self.assertIn(key, d)
+ for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
+ self.assertEqual(d.get(k, 100), v)
+
################################################################################
### Named Tuples