| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -156,6 +156,14 @@ def test_delete_connection_text_factory(self): | |||
| 156 | 156 | with self.assertRaises(AttributeError): | |
| 157 | 157 | del self.con.text_factory | |
| 158 | 158 | ||
| 159 | + def test_delete_cursor_row_factory(self): | ||
| 160 | + # gh-149738: deleting row_factory should raise an exception | ||
| 161 | + cur = self.con.cursor() | ||
| 162 | + with self.assertRaises(AttributeError): | ||
| 163 | + del cur.row_factory | ||
| 164 | + # Executing a query here should succeed. | ||
| 165 | + self.assertEqual(tuple(cur.execute("select 1").fetchone()), (1,)) | ||
| 166 | + | ||
| 159 | 167 | def test_sqlite_row_index_unicode(self): | |
| 160 | 168 | row = self.con.execute("select 1 as \xff").fetchone() | |
| 161 | 169 | self.assertEqual(row["\xff"], 1) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + :mod:`sqlite3`: Disallow removing the ``row_factory`` attribute of a cursor | ||
| 2 | + to prevent a crash on a query. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1402,13 +1402,33 @@ static struct PyMemberDef cursor_members[] = | |||
| 1402 | 1402 | {"description", _Py_T_OBJECT, offsetof(pysqlite_Cursor, description), Py_READONLY}, | |
| 1403 | 1403 | {"lastrowid", _Py_T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), Py_READONLY}, | |
| 1404 | 1404 | {"rowcount", Py_T_LONG, offsetof(pysqlite_Cursor, rowcount), Py_READONLY}, | |
| 1405 | - {"row_factory", _Py_T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, | ||
| 1406 | 1405 | {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), Py_READONLY}, | |
| 1407 | 1406 | {NULL} | |
| 1408 | 1407 | }; | |
| 1409 | 1408 | ||
| 1409 | + static PyObject * | ||
| 1410 | + cursor_get_row_factory(PyObject *op, void *Py_UNUSED(closure)) | ||
| 1411 | + { | ||
| 1412 | + pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op); | ||
| 1413 | + return Py_NewRef(self->row_factory); | ||
| 1414 | + } | ||
| 1415 | + | ||
| 1416 | + static int | ||
| 1417 | + cursor_set_row_factory(PyObject *op, PyObject *value, void *Py_UNUSED(closure)) | ||
| 1418 | + { | ||
| 1419 | + pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op); | ||
| 1420 | + if (value == NULL) { | ||
| 1421 | + PyErr_SetString(PyExc_AttributeError, | ||
| 1422 | + "cannot delete row_factory attribute"); | ||
| 1423 | + return -1; | ||
| 1424 | + } | ||
| 1425 | + Py_XSETREF(self->row_factory, Py_NewRef(value)); | ||
| 1426 | + return 0; | ||
| 1427 | + } | ||
| 1428 | + | ||
| 1410 | 1429 | static struct PyGetSetDef cursor_getsets[] = { | |
| 1411 | 1430 | _SQLITE3_CURSOR_ARRAYSIZE_GETSETDEF | |
| 1431 | + {"row_factory", cursor_get_row_factory, cursor_set_row_factory}, | ||
| 1412 | 1432 | {NULL}, | |
| 1413 | 1433 | }; | |
| 1414 | 1434 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments