]> granicus.if.org Git - python/commitdiff
bpo-32792: Preserve mapping order in ChainMap() (GH-5586)
authorRaymond Hettinger <rhettinger@users.noreply.github.com>
Sun, 11 Feb 2018 08:30:31 +0000 (00:30 -0800)
committerGitHub <noreply@github.com>
Sun, 11 Feb 2018 08:30:31 +0000 (00:30 -0800)
Lib/collections/__init__.py
Lib/test/test_collections.py
Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst [new file with mode: 0644]

index f0b41fd9d10d3e09bd9abe75888bc26c2810e8d3..9a753db71caeae47c6a0014f7b59638a410367b9 100644 (file)
@@ -920,7 +920,10 @@ class ChainMap(_collections_abc.MutableMapping):
         return len(set().union(*self.maps))     # reuses stored hash values if possible
 
     def __iter__(self):
-        return iter(set().union(*self.maps))
+        d = {}
+        for mapping in reversed(self.maps):
+            d.update(mapping)                   # reuses stored hash values if possible
+        return iter(d)
 
     def __contains__(self, key):
         return any(key in m for m in self.maps)
index a55239e57302e72aeb24a6604d2903a95f4b2e76..2099d236d0c4a1f299023407e5c6bb39fd167645 100644 (file)
@@ -141,6 +141,23 @@ class TestChainMap(unittest.TestCase):
         with self.assertRaises(KeyError):
             d.popitem()
 
+    def test_order_preservation(self):
+        d = ChainMap(
+                OrderedDict(j=0, h=88888),
+                OrderedDict(),
+                OrderedDict(i=9999, d=4444, c=3333),
+                OrderedDict(f=666, b=222, g=777, c=333, h=888),
+                OrderedDict(),
+                OrderedDict(e=55, b=22),
+                OrderedDict(a=1, b=2, c=3, d=4, e=5),
+                OrderedDict(),
+            )
+        self.assertEqual(''.join(d), 'abcdefghij')
+        self.assertEqual(list(d.items()),
+            [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
+             ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
+             ('i', 9999), ('j', 0)])
+
     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))
diff --git a/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst
new file mode 100644 (file)
index 0000000..1f7df62
--- /dev/null
@@ -0,0 +1 @@
+collections.ChainMap() preserves the order of the underlying mappings.