]> granicus.if.org Git - python/commitdiff
Backport 70140, 70141, 70143, and 70144.
authorRaymond Hettinger <python@rcn.com>
Tue, 3 Mar 2009 22:59:25 +0000 (22:59 +0000)
committerRaymond Hettinger <python@rcn.com>
Tue, 3 Mar 2009 22:59:25 +0000 (22:59 +0000)
Adds tests, switches from list to deque, fixes __reduce__
which was unnecessarily copying __keys.

Lib/collections.py
Lib/test/test_collections.py

index 331937827c658b1dbb4506e12d317ca0c2837156..0ff567306a540fb8ea817427987400f32f24df41 100644 (file)
@@ -27,11 +27,11 @@ class OrderedDict(dict, MutableMapping):
         except AttributeError:
             # Note the underlying data structure for this class is likely to
             # change in the future.  Do not rely on it or access it directly.
-            self.__keys = []
+            self.__keys = deque()
         self.update(*args, **kwds)
 
     def clear(self):
-        del self.__keys[:]
+        self.__keys.clear()
         dict.clear(self)
 
     def __setitem__(self, key, value):
@@ -58,16 +58,20 @@ class OrderedDict(dict, MutableMapping):
 
     def __reduce__(self):
         items = [[k, self[k]] for k in self]
+        tmp = self.__keys
+        del self.__keys
         inst_dict = vars(self).copy()
-        inst_dict.pop('__keys', None)
-        return (self.__class__, (items,), inst_dict)
+        self.__keys = tmp
+        if inst_dict:
+            return (self.__class__, (items,), inst_dict)
+        return self.__class__, (items,)
 
     setdefault = MutableMapping.setdefault
     update = MutableMapping.update
     pop = MutableMapping.pop
 
     def keys(self):
-        return self.__keys[:]
+        return list(self.__keys)
 
     def values(self):
         return map(self.__getitem__, self.__keys)
index 95022a1ed26d481b529e2a736e1fe5a8b3da935a..f232df4eeef2a24207b4f1964ba7fb857b5e8a6c 100644 (file)
@@ -717,6 +717,23 @@ class TestOrderedDict(unittest.TestCase):
             self.assertEquals(len(dup), len(od))
             self.assertEquals(type(dup), type(od))
 
+    def test_yaml_linkage(self):
+        # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
+        # In yaml, lists are native but tuples are not.
+        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+        od = OrderedDict(pairs)
+        # yaml.dump(od) -->
+        # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n  - [b, 2]\n'
+        self.assert_(all(type(pair)==list for pair in od.__reduce__()[1]))
+
+    def test_reduce_not_too_fat(self):
+        # do not save instance dictionary if not needed
+        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+        od = OrderedDict(pairs)
+        self.assertEqual(len(od.__reduce__()), 2)
+        od.x = 10
+        self.assertEqual(len(od.__reduce__()), 3)
+
     def test_repr(self):
         od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
         self.assertEqual(repr(od),