diff -r 031fc0231f3d Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/test/test_dictviews.py Sun Jan 18 10:11:25 2015 +0200 @@ -1,4 +1,5 @@ import unittest +import pickle from test import support class DictSetTest(unittest.TestCase): @@ -198,6 +199,20 @@ class DictSetTest(unittest.TestCase): d[42] = d.values() self.assertRaises(RuntimeError, repr, d) + def test_pickle(self): + d = {'a': 1, 'b': 2, 'c': 3} + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + keys = pickle.loads(pickle.dumps(d.keys(), proto)) + self.assertEqual(type(keys), type(d.keys())) + self.assertEqual(sorted(keys), sorted(d.keys())) + values = pickle.loads(pickle.dumps(d.values(), proto)) + self.assertEqual(type(values), type(d.values())) + self.assertEqual(sorted(values), sorted(d.values())) + items = pickle.loads(pickle.dumps(d.items(), proto)) + self.assertEqual(type(items), type(d.items())) + self.assertEqual(sorted(items), sorted(d.items())) + self.assertEqual(list(zip(keys, values)), list(items)) + def test_main(): support.run_unittest(DictSetTest) diff -r 031fc0231f3d Objects/dictobject.c --- a/Objects/dictobject.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Objects/dictobject.c Sun Jan 18 10:11:25 2015 +0200 @@ -3417,6 +3417,14 @@ dictkeys_contains(dictviewobject *dv, Py return PyDict_Contains((PyObject *)dv->dv_dict, obj); } +static PyObject* +dictkeys_reduce(dictviewobject *self) +{ + PyObject *m = PyObject_GetAttrString((PyObject *)Py_TYPE(self->dv_dict), + "keys"); + return Py_BuildValue("N(O)", m, self->dv_dict); +} + static PySequenceMethods dictkeys_as_sequence = { (lenfunc)dictview_len, /* sq_length */ 0, /* sq_concat */ @@ -3585,6 +3593,8 @@ PyDoc_STRVAR(isdisjoint_doc, static PyMethodDef dictkeys_methods[] = { {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, isdisjoint_doc}, + {"__reduce__", (PyCFunction)dictkeys_reduce, METH_NOARGS, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3657,6 +3667,14 @@ dictitems_contains(dictviewobject *dv, P return PyObject_RichCompareBool(value, found, Py_EQ); } +static PyObject* +dictitems_reduce(dictviewobject *self) +{ + PyObject *m = PyObject_GetAttrString((PyObject *)Py_TYPE(self->dv_dict), + "items"); + return Py_BuildValue("N(O)", m, self->dv_dict); +} + static PySequenceMethods dictitems_as_sequence = { (lenfunc)dictview_len, /* sq_length */ 0, /* sq_concat */ @@ -3671,6 +3689,8 @@ static PySequenceMethods dictitems_as_se static PyMethodDef dictitems_methods[] = { {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, isdisjoint_doc}, + {"__reduce__", (PyCFunction)dictitems_reduce, METH_NOARGS, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3724,6 +3744,14 @@ dictvalues_iter(dictviewobject *dv) return dictiter_new(dv->dv_dict, &PyDictIterValue_Type); } +static PyObject* +dictvalues_reduce(dictviewobject *self) +{ + PyObject *m = PyObject_GetAttrString((PyObject *)Py_TYPE(self->dv_dict), + "values"); + return Py_BuildValue("N(O)", m, self->dv_dict); +} + static PySequenceMethods dictvalues_as_sequence = { (lenfunc)dictview_len, /* sq_length */ 0, /* sq_concat */ @@ -3736,6 +3764,8 @@ static PySequenceMethods dictvalues_as_s }; static PyMethodDef dictvalues_methods[] = { + {"__reduce__", (PyCFunction)dictvalues_reduce, METH_NOARGS, + reduce_doc}, {NULL, NULL} /* sentinel */ };