Browse Source
bpo-42487: don't call __getitem__ of underlying maps in ChainMap.__iter__ (GH-23534)
pull/23577/head
Andreas Poehlmann
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with
18 additions and
1 deletions
-
Lib/collections/__init__.py
-
Lib/test/test_collections.py
-
Misc/NEWS.d/next/Library/2020-11-28-04-31-20.bpo-42487.iqtC4L.rst
|
|
|
@ -1001,7 +1001,7 @@ class ChainMap(_collections_abc.MutableMapping): |
|
|
|
def __iter__(self): |
|
|
|
d = {} |
|
|
|
for mapping in reversed(self.maps): |
|
|
|
d.update(mapping) # reuses stored hash values if possible |
|
|
|
d.update(dict.fromkeys(mapping)) # reuses stored hash values if possible |
|
|
|
return iter(d) |
|
|
|
|
|
|
|
def __contains__(self, key): |
|
|
|
|
|
|
|
@ -196,6 +196,22 @@ class TestChainMap(unittest.TestCase): |
|
|
|
('e', 55), ('f', 666), ('g', 777), ('h', 88888), |
|
|
|
('i', 9999), ('j', 0)]) |
|
|
|
|
|
|
|
def test_iter_not_calling_getitem_on_maps(self): |
|
|
|
class DictWithGetItem(UserDict): |
|
|
|
def __init__(self, *args, **kwds): |
|
|
|
self.called = False |
|
|
|
UserDict.__init__(self, *args, **kwds) |
|
|
|
def __getitem__(self, item): |
|
|
|
self.called = True |
|
|
|
UserDict.__getitem__(self, item) |
|
|
|
|
|
|
|
d = DictWithGetItem(a=1) |
|
|
|
c = ChainMap(d) |
|
|
|
d.called = False |
|
|
|
|
|
|
|
set(c) # iterate over chain map |
|
|
|
self.assertFalse(d.called, '__getitem__ was called') |
|
|
|
|
|
|
|
def test_dict_coercion(self): |
|
|
|
d = ChainMap(dict(a=1, b=2), dict(b=20, c=30)) |
|
|
|
self.assertEqual(dict(d), dict(a=1, b=2, c=30)) |
|
|
|
|
|
|
|
@ -0,0 +1 @@ |
|
|
|
ChainMap.__iter__ no longer calls __getitem__ on underlying maps |