From 28180837bf1359b6b658d3751e945fa4bd7c624a Mon Sep 17 00:00:00 2001 From: Owen Raccuglia Date: Wed, 1 Oct 2014 15:57:47 -0400 Subject: [PATCH] Allow pickling of cursor.description This is for people using dtuple.py; a dtuple.DatabaseTuple instance keeps a reference to cursor.description, which is not picklable because psycopg2 doesn't export the Column namedtuple it uses. This commit exports the Column namedtuple, and includes a test to verify the pickle/unpickle works after exporting Column. --- lib/__init__.py | 1 + psycopg/psycopgmodule.c | 1 + tests/test_cursor.py | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/lib/__init__.py b/lib/__init__.py index cf8c06ae..a67c0930 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -55,6 +55,7 @@ from psycopg2._psycopg import DateFromTicks, TimeFromTicks, TimestampFromTicks from psycopg2._psycopg import Error, Warning, DataError, DatabaseError, ProgrammingError from psycopg2._psycopg import IntegrityError, InterfaceError, InternalError from psycopg2._psycopg import NotSupportedError, OperationalError +from psycopg2._psycopg import Column from psycopg2._psycopg import _connect, apilevel, threadsafety, paramstyle from psycopg2._psycopg import __version__ diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c index e47c0e0f..daeff09f 100644 --- a/psycopg/psycopgmodule.c +++ b/psycopg/psycopgmodule.c @@ -895,6 +895,7 @@ INIT_MODULE(_psycopg)(void) PyModule_AddObject(module, "Notify", (PyObject*)¬ifyType); PyModule_AddObject(module, "Xid", (PyObject*)&xidType); PyModule_AddObject(module, "Diagnostics", (PyObject*)&diagnosticsType); + PyModule_AddObject(module, "Column", psyco_DescriptionType); #ifdef PSYCOPG_EXTENSIONS PyModule_AddObject(module, "lobject", (PyObject*)&lobjectType); #endif diff --git a/tests/test_cursor.py b/tests/test_cursor.py index 07956554..970cc37d 100755 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -23,6 +23,7 @@ # License for more details. import time +import pickle import psycopg2 import psycopg2.extensions from psycopg2.extensions import b @@ -400,6 +401,16 @@ class CursorTests(ConnectingTestCase): self.assertEqual(c.precision, None) self.assertEqual(c.scale, None) + def test_pickle_description(self): + curs = self.conn.cursor() + curs.execute('SELECT 1 AS foo') + description = curs.description + + pickled = pickle.dumps(description, pickle.HIGHEST_PROTOCOL) + unpickled = pickle.loads(pickled) + + self.assertEqual(description, unpickled) + @skip_before_postgres(8, 0) def test_named_cursor_stealing(self): # you can use a named cursor to iterate on a refcursor created