From 345077d5f78900ec95691ff047499526a4aabfbe Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 19 Jul 2013 15:57:27 +0100 Subject: [PATCH] Fixed pickling of exceptions with no pgerror/pgcode set Fixes ticket #170. --- NEWS | 7 +++++++ psycopg/error_type.c | 12 ++++++++++-- tests/test_module.py | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 7f366bb4..46cf5b5b 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,13 @@ Current release --------------- +What's new in psycopg 2.5.2 +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Fixed segfault pickling the exception raised on connection error + (:ticket:`#170`). + + What's new in psycopg 2.5.1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/psycopg/error_type.c b/psycopg/error_type.c index 106b87a7..75761e81 100644 --- a/psycopg/error_type.c +++ b/psycopg/error_type.c @@ -163,8 +163,16 @@ psyco_error_reduce(errorObject *self) if (2 != PyTuple_GET_SIZE(tuple)) { goto exit; } if (!(dict = PyDict_New())) { goto error; } - if (0 != PyDict_SetItemString(dict, "pgerror", self->pgerror)) { goto error; } - if (0 != PyDict_SetItemString(dict, "pgcode", self->pgcode)) { goto error; } + if (self->pgerror) { + if (0 != PyDict_SetItemString(dict, "pgerror", self->pgerror)) { + goto error; + } + } + if (self->pgcode) { + if (0 != PyDict_SetItemString(dict, "pgcode", self->pgcode)) { + goto error; + } + } { PyObject *newtuple; diff --git a/tests/test_module.py b/tests/test_module.py index 6f30b2e6..b2f5279d 100755 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -279,6 +279,21 @@ class ExceptionsTestCase(ConnectingTestCase): self.assertEqual(e.pgcode, e1.pgcode) self.assert_(e1.cursor is None) + @skip_before_python(2, 5) + def test_pickle_connection_error(self): + # segfaults on psycopg 2.5.1 - see ticket #170 + import pickle + try: + psycopg2.connect('dbname=nosuchdatabasemate') + except psycopg2.Error, exc: + e = exc + + e1 = pickle.loads(pickle.dumps(e)) + + self.assertEqual(e.pgerror, e1.pgerror) + self.assertEqual(e.pgcode, e1.pgcode) + self.assert_(e1.cursor is None) + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)