Skip to content

Commit c3fe3c3

Browse files
authored
gh-160929: Preserve ChainMap lookup values in reverse unions (gh-160932)
1 parent bf44248 commit c3fe3c3

3 files changed

Lines changed: 40 additions & 2 deletions

File tree

‎Lib/collections/__init__.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,8 +1163,7 @@ def __ror__(self, other):
11631163
if not isinstance(other, _collections_abc.Mapping):
11641164
return NotImplemented
11651165
m = dict(other)
1166-
for child in reversed(self.maps):
1167-
m.update(child)
1166+
m.update(self)
11681167
return self.__class__(m)
11691168

11701169

‎Lib/test/test_collections.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,42 @@ def __ror__(self, other):
309309
self.assertIs(type(tmp), SubclassRor)
310310
self.assertIs(type(tmp.maps[0]), dict)
311311

312+
def test_reverse_union_with_counter(self):
313+
left = {'shared': 99, 'left_only': 3}
314+
front = Counter(front=2)
315+
back = {'shadowed': 5, 'shared': 7, 'back': 9}
316+
cm = ChainMap(front, back)
317+
318+
self.assertEqual(cm['shadowed'], 0)
319+
result = left | cm
320+
self.assertEqual(list(result.items()), [
321+
('shared', 0), ('left_only', 3), ('shadowed', 0),
322+
('back', 0), ('front', 2),
323+
])
324+
self.assertEqual(left, {'shared': 99, 'left_only': 3})
325+
self.assertEqual(dict(front), {'front': 2})
326+
self.assertEqual(back, {'shadowed': 5, 'shared': 7, 'back': 9})
327+
328+
def test_reverse_union_with_defaultdict(self):
329+
left = {'shared': 99, 'left_only': 3}
330+
front = collections.defaultdict(lambda: -1, {'front': 2})
331+
back = {'shadowed': 5, 'shared': 7}
332+
cm = ChainMap(front, back)
333+
334+
fresh_front = collections.defaultdict(lambda: -1, {'front': 2})
335+
fresh = ChainMap(fresh_front, {'shadowed': 5, 'shared': 7})
336+
self.assertEqual(fresh['shadowed'], -1)
337+
self.assertEqual(fresh['shared'], -1)
338+
self.assertEqual(fresh_front, {'front': 2, 'shadowed': -1, 'shared': -1})
339+
340+
result = left | cm
341+
self.assertEqual(list(result.items()), [
342+
('shared', -1), ('left_only', 3), ('shadowed', -1), ('front', 2),
343+
])
344+
self.assertEqual(left, {'shared': 99, 'left_only': 3})
345+
self.assertEqual(front, {'front': 2, 'shadowed': -1, 'shared': -1})
346+
self.assertEqual(back, {'shadowed': 5, 'shared': 7})
347+
312348

313349
################################################################################
314350
### Named Tuples
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix reverse union with :class:`~collections.ChainMap` to preserve its lookup
2+
semantics for defaulting mappings such as :class:`~collections.Counter` and
3+
:class:`~collections.defaultdict`.

0 commit comments

Comments
 (0)