diff -r 775158408ecb Doc/library/sqlite3.rst --- a/Doc/library/sqlite3.rst Sat Aug 27 09:42:40 2016 -0700 +++ b/Doc/library/sqlite3.rst Sun Aug 28 03:10:33 2016 +0800 @@ -285,11 +285,11 @@ .. versionadded:: 3.2 - .. method:: cursor([cursorClass]) + .. method:: cursor(factory=sqlite3.Cursor) - The cursor method accepts a single optional parameter *cursorClass*. If - supplied, this must be a custom cursor class that extends - :class:`sqlite3.Cursor`. + The cursor method accepts a single optional parameter *factory*. If + supplied, this must be a callable returning an instance of :class:`sqlite3.Cursor` + or its subclasses. .. method:: commit() diff -r 775158408ecb Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py Sat Aug 27 09:42:40 2016 -0700 +++ b/Lib/sqlite3/test/factory.py Sun Aug 28 03:10:33 2016 +0800 @@ -58,8 +58,17 @@ self.con.close() def CheckIsInstance(self): - cur = self.con.cursor(factory=MyCursor) + cur = self.con.cursor() + self.assertIsInstance(cur, sqlite.Cursor) + cur = self.con.cursor(MyCursor) self.assertIsInstance(cur, MyCursor) + cur = self.con.cursor(factory=lambda con: MyCursor(con)) + self.assertIsInstance(cur, MyCursor) + + def CheckInvalidFactory(self): + self.assertRaises(TypeError, self.con.cursor, None) # not callable + self.assertRaises(TypeError, self.con.cursor, lambda: None) # invalid callable + self.assertRaises(TypeError, self.con.cursor, lambda con: None) # return a non-cursor class RowFactoryTestsBackwardsCompat(unittest.TestCase): def setUp(self): @@ -183,10 +192,12 @@ def CheckFakeCursorClass(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # segmentation fault. + # Issue #27861: Also appies for cursor factory. class FakeCursor(str): __class__ = sqlite.Cursor - cur = self.con.cursor(factory=FakeCursor) - self.assertRaises(TypeError, sqlite.Row, cur, ()) + self.con.row_factory = sqlite.Row + self.assertRaises(TypeError, self.con.cursor, FakeCursor) + self.assertRaises(TypeError, sqlite.Row, FakeCursor(), ()) def tearDown(self): self.con.close() diff -r 775158408ecb Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c Sat Aug 27 09:42:40 2016 -0700 +++ b/Modules/_sqlite/connection.c Sun Aug 28 03:10:33 2016 +0800 @@ -300,7 +300,7 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { - static char *kwlist[] = {"factory", NULL, NULL}; + static char *kwlist[] = {"factory", NULL}; PyObject* factory = NULL; PyObject* cursor; @@ -317,7 +317,16 @@ factory = (PyObject*)&pysqlite_CursorType; } - cursor = PyObject_CallFunction(factory, "O", self); + cursor = PyObject_CallFunctionObjArgs(factory, (PyObject *)self, NULL); + if (cursor == NULL) + return NULL; + if (PyObject_TypeCheck(cursor, &pysqlite_CursorType) == 0) { + PyErr_Format(PyExc_TypeError, + "factory must return a cursor, not %s", + Py_TYPE(cursor)->tp_name); + Py_DECREF(cursor); + return NULL; + } _pysqlite_drop_unused_cursor_references(self);