diff -r a3ee325fd489 Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py Thu Jun 26 13:33:05 2014 -0400 +++ b/Lib/sqlite3/test/factory.py Mon Jul 14 10:21:11 2014 +0300 @@ -22,6 +22,7 @@ # 3. This notice may not be removed or altered from any source distribution. import unittest +import pickle import sqlite3 as sqlite from collections.abc import Sequence @@ -162,6 +163,15 @@ self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) + def CheckPickle(self): + self.con.row_factory = sqlite.Row + row = self.con.execute("select 1 as a, 2 as b").fetchone() + dump = pickle.dumps(row) + load = pickle.loads(dump) + self.assertEqual(row.keys(), load.keys()) + self.assertEqual(load['a'], 1) + self.assertEqual(load['b'], 2) + def tearDown(self): self.con.close() diff -r a3ee325fd489 Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c Thu Jun 26 13:33:05 2014 -0400 +++ b/Modules/_sqlite/row.c Mon Jul 14 10:21:11 2014 +0300 @@ -63,6 +63,33 @@ return 0; } +static PyObject * +pysqlite_row_setstate(pysqlite_Row* self, PyObject *state) +{ + PyObject *description, *data; + if (!PyArg_ParseTuple(state, "OO", &description, &data)) + return NULL; + Py_CLEAR(self->description); + self->description = description; + Py_INCREF(self->description); + Py_CLEAR(self->data); + self->data = data; + Py_INCREF(self->data); + Py_RETURN_NONE; +} + +static PyObject * +pysqlite_row_getstate(pysqlite_Row *self) +{ + PyObject *state; + + state = Py_BuildValue("(OO)", + self->description ? self->description : Py_None, + self->data ? self->data: Py_None); + return state; +} + + PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) { PyObject* item = PyTuple_GetItem(self->data, idx); @@ -220,6 +247,8 @@ static PyMethodDef pysqlite_row_methods[] = { {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, PyDoc_STR("Returns the keys of the row.")}, + {"__getstate__", (PyCFunction)pysqlite_row_getstate, METH_NOARGS}, + {"__setstate__", (PyCFunction)pysqlite_row_setstate, METH_O}, {NULL, NULL} };