| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -285,11 +285,11 @@ Connection Objects | |||
| 285 | 285 | ||
| 286 | 286 | .. versionadded:: 3.2 | |
| 287 | 287 | ||
| 288 | - .. method:: cursor([cursorClass]) | ||
| 288 | + .. method:: cursor(factory=Cursor) | ||
| 289 | 289 | ||
| 290 | - The cursor method accepts a single optional parameter *cursorClass*. If | ||
| 291 | - supplied, this must be a custom cursor class that extends | ||
| 292 | - :class:`sqlite3.Cursor`. | ||
| 290 | + The cursor method accepts a single optional parameter *factory*. If | ||
| 291 | + supplied, this must be a callable returning an instance of :class:`Cursor` | ||
| 292 | + or its subclasses. | ||
| 293 | 293 | ||
| 294 | 294 | .. method:: commit() | |
| 295 | 295 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -58,9 +58,21 @@ def tearDown(self): | |||
| 58 | 58 | self.con.close() | |
| 59 | 59 | ||
| 60 | 60 | def CheckIsInstance(self): | |
| 61 | - cur = self.con.cursor(factory=MyCursor) | ||
| 61 | + cur = self.con.cursor() | ||
| 62 | + self.assertIsInstance(cur, sqlite.Cursor) | ||
| 63 | + cur = self.con.cursor(MyCursor) | ||
| 64 | + self.assertIsInstance(cur, MyCursor) | ||
| 65 | + cur = self.con.cursor(factory=lambda con: MyCursor(con)) | ||
| 62 | 66 | self.assertIsInstance(cur, MyCursor) | |
| 63 | 67 | ||
| 68 | + def CheckInvalidFactory(self): | ||
| 69 | + # not a callable at all | ||
| 70 | + self.assertRaises(TypeError, self.con.cursor, None) | ||
| 71 | + # invalid callable with not exact one argument | ||
| 72 | + self.assertRaises(TypeError, self.con.cursor, lambda: None) | ||
| 73 | + # invalid callable returning non-cursor | ||
| 74 | + self.assertRaises(TypeError, self.con.cursor, lambda con: None) | ||
| 75 | + | ||
| 64 | 76 | class RowFactoryTestsBackwardsCompat(unittest.TestCase): | |
| 65 | 77 | def setUp(self): | |
| 66 | 78 | self.con = sqlite.connect(":memory:") | |
@@ -183,10 +195,12 @@ def CheckSqliteRowAsSequence(self): | |||
| 183 | 195 | def CheckFakeCursorClass(self): | |
| 184 | 196 | # Issue #24257: Incorrect use of PyObject_IsInstance() caused | |
| 185 | 197 | # segmentation fault. | |
| 198 | + # Issue #27861: Also applies for cursor factory. | ||
| 186 | 199 | class FakeCursor(str): | |
| 187 | 200 | __class__ = sqlite.Cursor | |
| 188 | - cur = self.con.cursor(factory=FakeCursor) | ||
| 189 | - self.assertRaises(TypeError, sqlite.Row, cur, ()) | ||
| 201 | + self.con.row_factory = sqlite.Row | ||
| 202 | + self.assertRaises(TypeError, self.con.cursor, FakeCursor) | ||
| 203 | + self.assertRaises(TypeError, sqlite.Row, FakeCursor(), ()) | ||
| 190 | 204 | ||
| 191 | 205 | def tearDown(self): | |
| 192 | 206 | self.con.close() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -50,6 +50,9 @@ Core and Builtins | |||
| 50 | 50 | Library | |
| 51 | 51 | ------- | |
| 52 | 52 | ||
| 53 | + - Issue #27861: Fixed a crash in sqlite3.Connection.cursor() when a factory | ||
| 54 | + creates not a cursor. Patch by Xiang Zhang. | ||
| 55 | + | ||
| 53 | 56 | - Issue #19884: Avoid spurious output on OS X with Gnu Readline. | |
| 54 | 57 | ||
| 55 | 58 | - Issue #10513: Fix a regression in Connection.commit(). Statements should | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -300,7 +300,7 @@ int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObjec | |||
| 300 | 300 | ||
| 301 | 301 | PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) | |
| 302 | 302 | { | |
| 303 | - static char *kwlist[] = {"factory", NULL, NULL}; | ||
| 303 | + static char *kwlist[] = {"factory", NULL}; | ||
| 304 | 304 | PyObject* factory = NULL; | |
| 305 | 305 | PyObject* cursor; | |
| 306 | 306 | ||
@@ -317,7 +317,16 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, | |||
| 317 | 317 | factory = (PyObject*)&pysqlite_CursorType; | |
| 318 | 318 | } | |
| 319 | 319 | ||
| 320 | - cursor = PyObject_CallFunction(factory, "O", self); | ||
| 320 | + cursor = PyObject_CallFunctionObjArgs(factory, (PyObject *)self, NULL); | ||
| 321 | + if (cursor == NULL) | ||
| 322 | + return NULL; | ||
| 323 | + if (!PyObject_TypeCheck(cursor, &pysqlite_CursorType)) { | ||
| 324 | + PyErr_Format(PyExc_TypeError, | ||
| 325 | + "factory must return a cursor, not %.100s", | ||
| 326 | + Py_TYPE(cursor)->tp_name); | ||
| 327 | + Py_DECREF(cursor); | ||
| 328 | + return NULL; | ||
| 329 | + } | ||
| 321 | 330 | ||
| 322 | 331 | _pysqlite_drop_unused_cursor_references(self); | |
| 323 | 332 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments