diff --git a/NEWS b/NEWS index 07a1e7eb..653d9695 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,8 @@ What's new in psycopg 2.5.3 happens for TCP connections instead (:ticket:`#196`). - Fixed overflow opening a lobject with an oid not fitting in a signed int (:ticket:`#203`). +- Fixed handling of explicit default ``cursor_factory=None`` in + `connection.cursor()` (:ticket:`#210`). - Fixed possible segfault in named cursors creation. - Fixed debug build on Windows, thanks to James Emerton. diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index cb47b662..99235250 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -55,7 +55,7 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *kwargs) PyObject *obj = NULL; PyObject *rv = NULL; PyObject *name = Py_None; - PyObject *factory = (PyObject *)&cursorType; + PyObject *factory = Py_None; PyObject *withhold = Py_False; PyObject *scrollable = Py_None; @@ -64,16 +64,21 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *kwargs) EXC_IF_CONN_CLOSED(self); - if (self->cursor_factory && self->cursor_factory != Py_None) { - factory = self->cursor_factory; - } - if (!PyArg_ParseTupleAndKeywords( args, kwargs, "|OOOO", kwlist, &name, &factory, &withhold, &scrollable)) { goto exit; } + if (factory == Py_None) { + if (self->cursor_factory && self->cursor_factory != Py_None) { + factory = self->cursor_factory; + } + else { + factory = (PyObject *)&cursorType; + } + } + if (self->status != CONN_STATUS_READY && self->status != CONN_STATUS_BEGIN && self->status != CONN_STATUS_PREPARED) { diff --git a/tests/test_connection.py b/tests/test_connection.py index a58d8eb6..21f7a499 100755 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -249,6 +249,16 @@ class ConnectionTests(ConnectingTestCase): cur.execute("select 1 as a") self.assertRaises(TypeError, (lambda r: r['a']), cur.fetchone()) + def test_cursor_factory_none(self): + # issue #210 + conn = self.connect() + cur = conn.cursor(cursor_factory=None) + self.assertEqual(type(cur), psycopg2.extensions.cursor) + + conn = self.connect(cursor_factory=psycopg2.extras.DictCursor) + cur = conn.cursor(cursor_factory=None) + self.assertEqual(type(cur), psycopg2.extras.DictCursor) + def test_failed_init_status(self): class SubConnection(psycopg2.extensions.connection): def __init__(self, dsn):