mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Correctly implement isolation_level setter to handle deletion (#5983)
This commit is contained in:
2
Lib/test/test_sqlite3/test_regression.py
vendored
2
Lib/test/test_sqlite3/test_regression.py
vendored
@@ -409,8 +409,6 @@ class RegressionTests(unittest.TestCase):
|
||||
del ref
|
||||
support.gc_collect()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_del_isolation_level_segfault(self):
|
||||
with self.assertRaises(AttributeError):
|
||||
del self.con.isolation_level
|
||||
|
||||
@@ -61,7 +61,10 @@ mod _sqlite {
|
||||
PyInt, PyIntRef, PySlice, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef,
|
||||
},
|
||||
convert::IntoObject,
|
||||
function::{ArgCallable, ArgIterable, FsPath, FuncArgs, OptionalArg, PyComparisonValue},
|
||||
function::{
|
||||
ArgCallable, ArgIterable, FsPath, FuncArgs, OptionalArg, PyComparisonValue,
|
||||
PySetterValue,
|
||||
},
|
||||
object::{Traverse, TraverseFn},
|
||||
protocol::{PyBuffer, PyIterReturn, PyMappingMethods, PySequence, PySequenceMethods},
|
||||
sliceable::{SaturatedSliceIter, SliceableSequenceOp},
|
||||
@@ -1357,22 +1360,32 @@ mod _sqlite {
|
||||
self.isolation_level.deref().map(|x| x.to_owned())
|
||||
}
|
||||
#[pygetset(setter)]
|
||||
fn set_isolation_level(&self, val: Option<PyStrRef>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Some(val) = &val {
|
||||
begin_statement_ptr_from_isolation_level(val, vm)?;
|
||||
}
|
||||
fn set_isolation_level(
|
||||
&self,
|
||||
value: PySetterValue<Option<PyStrRef>>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
match value {
|
||||
PySetterValue::Assign(value) => {
|
||||
if let Some(val_str) = &value {
|
||||
begin_statement_ptr_from_isolation_level(val_str, vm)?;
|
||||
}
|
||||
|
||||
// If setting isolation_level to None (auto-commit mode), commit any pending transaction
|
||||
if val.is_none() {
|
||||
let db = self.db_lock(vm)?;
|
||||
if !db.is_autocommit() {
|
||||
// Keep the lock and call implicit_commit directly to avoid race conditions
|
||||
db.implicit_commit(vm)?;
|
||||
// If setting isolation_level to None (auto-commit mode), commit any pending transaction
|
||||
if value.is_none() {
|
||||
let db = self.db_lock(vm)?;
|
||||
if !db.is_autocommit() {
|
||||
// Keep the lock and call implicit_commit directly to avoid race conditions
|
||||
db.implicit_commit(vm)?;
|
||||
}
|
||||
}
|
||||
let _ = unsafe { self.isolation_level.swap(value) };
|
||||
Ok(())
|
||||
}
|
||||
PySetterValue::Delete => Err(vm.new_attribute_error(
|
||||
"'isolation_level' attribute cannot be deleted".to_owned(),
|
||||
)),
|
||||
}
|
||||
|
||||
let _ = unsafe { self.isolation_level.swap(val) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
|
||||
Reference in New Issue
Block a user