Skip to content

Commit

Permalink
support deepcopy & copy & getstate & setstate & pickle
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangyuncong committed Apr 9, 2018
1 parent 1cfa795 commit d6f2872
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 6 deletions.
54 changes: 48 additions & 6 deletions src/fastpb/template/module.jinjacc
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,23 @@ namespace {
return PyString_FromStringAndSize(result.data(), result.length());
}

PyObject *
{{ message.name }}_Copy({{ message.name }}* self)
{
{{ message.name }}* cloned = NULL;
Py_BEGIN_ALLOW_THREADS
cloned = ({{ message.name }}*){{ message.name }}_new(&{{ message.name }}Type, NULL, NULL);
cloned->protobuf->CopyFrom(*self->protobuf);
Py_END_ALLOW_THREADS
return (PyObject*)cloned;
}

PyObject *
{{ message.name }}_DeepCopy({{ message.name }}* self, PyObject* /*memo*/)
{
return {{ message.name }}_Copy(self);
}


PyObject *
{{ message.name }}_ParseFromString({{ message.name }}* self, PyObject *value)
Expand All @@ -214,6 +231,18 @@ namespace {
Py_RETURN_NONE;
}

PyObject *
{{ message.name }}_Reduce({{ message.name }}* self)
{
PyObject* ret = PyTuple_New(3);
PyObject* type_object = (PyObject*)Py_TYPE(self);
Py_INCREF(type_object);
PyObject* state = {{ message.name }}_SerializeToString(self);
PyTuple_SetItem(ret, 0, type_object);
PyTuple_SetItem(ret, 1, PyTuple_New(0));
PyTuple_SetItem(ret, 1, state);
return ret;
}

PyObject *
{{ message.name }}_ParseFromLongString({{ message.name }}* self, PyObject *value)
Expand Down Expand Up @@ -658,10 +687,23 @@ namespace {
{"ParseMany", (PyCFunction){{ message.name }}_ParseMany, METH_VARARGS | METH_CLASS,
"Parses many protocol buffers of this type from a string."
},
{"__copy__", (PyCFunction){{ message.name }}_DeepCopy, METH_NOARGS,
"copy a pb message."
},
{"__deepcopy__", (PyCFunction){{ message.name }}_DeepCopy, METH_O,
"deep copy a pb message."
},
{"__getstate__", (PyCFunction){{ message.name }}_SerializeToString, METH_NOARGS,
"support getstate"
},
{"__setstate__", (PyCFunction){{ message.name }}_ParseFromString, METH_O,
"support setstate"
},
{"__reduce__", (PyCFunction){{ message.name }}_Reduce, METH_NOARGS,
"support pickle"
},
{NULL} // Sentinel
};


PyTypeObject {{ message.name }}Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
Expand All @@ -688,9 +730,9 @@ namespace {
0, /* tp_traverse */
0, /* tp_clear */
{{ message.name }}_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
{{ message.name }}_methods, /* tp_methods */
{{ message.name }}_members, /* tp_members */
{{ message.name }}_getsetters, /* tp_getset */
Expand All @@ -711,7 +753,7 @@ static PyMethodDef module_methods[] = {
{NULL} // Sentinel
};

#ifndef PyMODINIT_FUNC // Declarations for DLL import/export.
#ifndef PyMODINIT_FUNC // Declarations for DLL import/export.
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
Expand Down
11 changes: 11 additions & 0 deletions src/fastpb/template/test.jinjapy
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"""Auto-generated unit tests."""

import unittest
import copy
import cPickle

{% for file in files %}
import {{ file.package }}
Expand Down Expand Up @@ -54,6 +56,15 @@ class Test_{{ file.package.replace('.', '_') }}(unittest.TestCase):
{% for field in message.field %}
self.assertEquals(pb.{{ field.name }}, pb2.{{ field.name }})
{% endfor %}

pb3 = copy.deepcopy(pb)
pb4 = cPickle.loads(cPickle.dumps(pb3))

{% for field in message.field %}
self.assertEquals(pb.{{ field.name }}, pb3.{{ field.name }})
self.assertEquals(pb.{{ field.name }}, pb4.{{ field.name }})
{% endfor %}

{% endfor %}
{% endfor %}

Expand Down

0 comments on commit d6f2872

Please sign in to comment.