Skip to content

Commit 4276e0c

Browse files
committed
Implement pickle support
1 parent a9dc2d8 commit 4276e0c

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

immutables/_map.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3306,6 +3306,42 @@ map_py_hash(MapObject *self)
33063306
return self->h_hash;
33073307
}
33083308

3309+
static PyObject *
3310+
map_reduce(MapObject *self)
3311+
{
3312+
MapIteratorState iter;
3313+
map_iter_t iter_res;
3314+
3315+
PyObject *dict = PyDict_New();
3316+
if (dict == NULL) {
3317+
return NULL;
3318+
}
3319+
3320+
map_iterator_init(&iter, self->h_root);
3321+
do {
3322+
PyObject *key;
3323+
PyObject *val;
3324+
3325+
iter_res = map_iterator_next(&iter, &key, &val);
3326+
if (iter_res == I_ITEM) {
3327+
if (PyDict_SetItem(dict, key, val) < 0) {
3328+
Py_DECREF(dict);
3329+
return NULL;
3330+
}
3331+
}
3332+
} while (iter_res != I_END);
3333+
3334+
PyObject *args = PyTuple_Pack(1, dict);
3335+
Py_DECREF(dict);
3336+
if (args == NULL) {
3337+
return NULL;
3338+
}
3339+
3340+
PyObject *tup = PyTuple_Pack(2, Py_TYPE(self), args);
3341+
Py_DECREF(args);
3342+
return tup;
3343+
}
3344+
33093345

33103346
static PyMethodDef Map_methods[] = {
33113347
{"set", (PyCFunction)map_py_set, METH_VARARGS, NULL},
@@ -3316,6 +3352,7 @@ static PyMethodDef Map_methods[] = {
33163352
{"keys", (PyCFunction)map_py_keys, METH_NOARGS, NULL},
33173353
{"values", (PyCFunction)map_py_values, METH_NOARGS, NULL},
33183354
{"update", (PyCFunction)map_py_update, METH_VARARGS | METH_KEYWORDS, NULL},
3355+
{"__reduce__", (PyCFunction)map_reduce, METH_NOARGS, NULL},
33193356
{"__dump__", (PyCFunction)map_py_dump, METH_NOARGS, NULL},
33203357
{NULL, NULL}
33213358
};

immutables/map.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ def _new(cls, count, root):
450450
m.__hash = -1
451451
return m
452452

453+
def __reduce__(self):
454+
return (type(self), (dict(self.items()),))
455+
453456
def __len__(self):
454457
return self.__count
455458

tests/test_map.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import collections.abc
22
import gc
3+
import pickle
34
import random
45
import unittest
56
import weakref
@@ -1148,6 +1149,15 @@ def test_map_mut_stress(self):
11481149
self.assertEqual(dict(h.items()), d)
11491150
self.assertEqual(len(h), len(d))
11501151

1152+
def test_map_pickle(self):
1153+
h = self.Map(a=1, b=2)
1154+
for proto in range(pickle.HIGHEST_PROTOCOL):
1155+
p = pickle.dumps(h, proto)
1156+
uh = pickle.loads(p)
1157+
1158+
self.assertTrue(isinstance(uh, self.Map))
1159+
self.assertEqual(h, uh)
1160+
11511161

11521162
class PyMapTest(BaseMapTest, unittest.TestCase):
11531163

0 commit comments

Comments
 (0)