Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_sqlite3/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,6 @@ def callback(*args):
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
Expand Down
43 changes: 29 additions & 14 deletions stdlib/src/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -1350,22 +1353,34 @@ 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, vm: &VirtualMachine) -> PyResult<()> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn set_isolation_level(&self, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
fn set_isolation_level(&self, value: PySetterValue<Option<PyStrRef>>, vm: &VirtualMachine) -> PyResult<()> {

How about trying this?

match value {
PySetterValue::Assign(new_value) => {
let val = if vm.is_none(&new_value) {
None
} else {
Some(new_value.try_into_value::<PyStrRef>(vm)?)
};

if let Some(val_str) = &val {
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 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)?;
}
}
let _ = unsafe { self.isolation_level.swap(val) };
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]
Expand Down
Loading