diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index f23129d7e3275e7..2239787dd6b51aa 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1163,8 +1163,7 @@ def __ror__(self, other): if not isinstance(other, _collections_abc.Mapping): return NotImplemented m = dict(other) - for child in reversed(self.maps): - m.update(child) + m.update(self) return self.__class__(m) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index b1b2dd2ca5ca0db..8bd5cf478f44b03 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -309,6 +309,42 @@ def __ror__(self, other): self.assertIs(type(tmp), SubclassRor) self.assertIs(type(tmp.maps[0]), dict) + def test_reverse_union_with_counter(self): + left = {'shared': 99, 'left_only': 3} + front = Counter(front=2) + back = {'shadowed': 5, 'shared': 7, 'back': 9} + cm = ChainMap(front, back) + + self.assertEqual(cm['shadowed'], 0) + result = left | cm + self.assertEqual(list(result.items()), [ + ('shared', 0), ('left_only', 3), ('shadowed', 0), + ('back', 0), ('front', 2), + ]) + self.assertEqual(left, {'shared': 99, 'left_only': 3}) + self.assertEqual(dict(front), {'front': 2}) + self.assertEqual(back, {'shadowed': 5, 'shared': 7, 'back': 9}) + + def test_reverse_union_with_defaultdict(self): + left = {'shared': 99, 'left_only': 3} + front = collections.defaultdict(lambda: -1, {'front': 2}) + back = {'shadowed': 5, 'shared': 7} + cm = ChainMap(front, back) + + fresh_front = collections.defaultdict(lambda: -1, {'front': 2}) + fresh = ChainMap(fresh_front, {'shadowed': 5, 'shared': 7}) + self.assertEqual(fresh['shadowed'], -1) + self.assertEqual(fresh['shared'], -1) + self.assertEqual(fresh_front, {'front': 2, 'shadowed': -1, 'shared': -1}) + + result = left | cm + self.assertEqual(list(result.items()), [ + ('shared', -1), ('left_only', 3), ('shadowed', -1), ('front', 2), + ]) + self.assertEqual(left, {'shared': 99, 'left_only': 3}) + self.assertEqual(front, {'front': 2, 'shadowed': -1, 'shared': -1}) + self.assertEqual(back, {'shadowed': 5, 'shared': 7}) + ################################################################################ ### Named Tuples diff --git a/Misc/NEWS.d/next/Library/2026-10-29-21-36-08.gh-issue-160929.mK8n2Q.rst b/Misc/NEWS.d/next/Library/2026-10-29-21-36-08.gh-issue-160929.mK8n2Q.rst new file mode 100644 index 000000000000000..09bd1e568e7e9bd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-29-21-36-08.gh-issue-160929.mK8n2Q.rst @@ -0,0 +1,3 @@ +Fix reverse union with :class:`~collections.ChainMap` to preserve its lookup +semantics for defaulting mappings such as :class:`~collections.Counter` and +:class:`~collections.defaultdict`.