diff -r 149490bbd260 Lib/collections/__init__.py --- a/Lib/collections/__init__.py Sat Nov 01 07:40:22 2014 -0700 +++ b/Lib/collections/__init__.py Sun Nov 02 16:51:38 2014 +0200 @@ -226,13 +226,24 @@ class OrderedDict(dict): return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, list(self.items())) - def __reduce__(self): + def __reduce_ex__(self, proto): 'Return state information for pickling' inst_dict = vars(self).copy() for k in vars(OrderedDict()): inst_dict.pop(k, None) + if proto < 3: + # Support PyYAML's dump() feature. + # In yaml, lists are native but tuples are not. + items = [[k, self[k]] for k in self] + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) return self.__class__, (), inst_dict or None, None, iter(self.items()) + def __reduce__(self): + 'Return state information for pickling' + return self.__reduce_ex__(0) + def copy(self): 'od.copy() -> a shallow copy of od' return self.__class__(self) diff -r 149490bbd260 Lib/test/test_collections.py --- a/Lib/test/test_collections.py Sat Nov 01 07:40:22 2014 -0700 +++ b/Lib/test/test_collections.py Sun Nov 02 16:51:38 2014 +0200 @@ -1490,24 +1490,33 @@ class TestOrderedDict(unittest.TestCase) 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)] + 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.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1])) + for rv in (od.__reduce__(), od.__reduce_ex__(2)): + self.assertEqual(len(rv), 2) + self.assertEqual(len(rv[1]), 1) + for i, pair in enumerate(rv[1][0]): + self.assertEqual(type(pair), list, (i, pair)) + self.assertEqual(rv[1][0], pairs) 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.assertIsNone(od.__reduce__()[2]) - od.x = 10 - self.assertIsNotNone(od.__reduce__()[2]) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + od = OrderedDict(pairs) + rv = od.__reduce_ex__(proto) + if len(rv) > 2: + self.assertIsNone(rv[2]) + od.x = 10 + rv = od.__reduce_ex__(proto) + self.assertIsNotNone(rv[2]) def test_pickle_recursive(self): od = OrderedDict() od[1] = od - for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): + for proto in range(3, pickle.HIGHEST_PROTOCOL + 1): dup = pickle.loads(pickle.dumps(od, proto)) self.assertIsNot(dup, od) self.assertEqual(list(dup.keys()), [1])