diff options
author | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2013-01-11 23:39:53 (GMT) |
---|---|---|
committer | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2013-01-11 23:39:53 (GMT) |
commit | 1ba81ee19a25d52df2d5ce193375086164b1ca77 (patch) | |
tree | 6f91d0f4827fa62e35d98c6125f2156b24f552fc /Lib | |
parent | 569ff4fbbc4cd0589c369519745d8d17bf3094b0 (diff) | |
download | cpython-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__.py | 11 | ||||
-rw-r--r-- | Lib/test/test_collections.py | 32 |
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 |