mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
feat(stdlib/sqlite): Implement slice assignment for Blob (#6039)
This commit is contained in:
1 parent
4079776c36
commit
38ca076cb5
2 files changed
+57
-16
No files matched your search
Vendored
-10
@@ -1322,8 +1322,6 @@ class BlobTests(unittest.TestCase):
|
||||
expected = b"This blob data string is exactly fifty bytes long."
|
||||
self.assertEqual(self.blob.read(), expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_blob_set_slice_buffer_object(self):
|
||||
from array import array
|
||||
self.blob[0:5] = memoryview(b"12345")
|
||||
@@ -1351,22 +1349,16 @@ class BlobTests(unittest.TestCase):
|
||||
def test_blob_get_slice_with_skip(self):
|
||||
self.assertEqual(self.blob[0:10:2], b"ti lb")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_blob_set_slice(self):
|
||||
self.blob[0:5] = b"12345"
|
||||
expected = b"12345" + self.data[5:]
|
||||
actual = self.cx.execute("select b from test").fetchone()[0]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_blob_set_empty_slice(self):
|
||||
self.blob[0:0] = b""
|
||||
self.assertEqual(self.blob[:], self.data)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_blob_set_slice_with_skip(self):
|
||||
self.blob[0:10:2] = b"12345"
|
||||
actual = self.cx.execute("select b from test").fetchone()[0]
|
||||
@@ -1419,8 +1411,6 @@ class BlobTests(unittest.TestCase):
|
||||
with self.assertRaisesRegex(ValueError, "must be in range"):
|
||||
self.blob[0] = 2**65
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_blob_set_slice_error(self):
|
||||
with self.assertRaisesRegex(IndexError, "wrong size"):
|
||||
self.blob[5:10] = b"a"
|
||||
|
||||
+57
-6
@@ -2238,11 +2238,12 @@ mod _sqlite {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let Some(value) = value else {
|
||||
return Err(vm.new_type_error("Blob doesn't support deletion"));
|
||||
return Err(vm.new_type_error("Blob doesn't support slice deletion"));
|
||||
};
|
||||
let inner = self.inner(vm)?;
|
||||
|
||||
if let Some(index) = needle.try_index_opt(vm) {
|
||||
// Handle single item assignment: blob[i] = b
|
||||
let Some(value) = value.downcast_ref::<PyInt>() else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"'{}' object cannot be interpreted as an integer",
|
||||
@@ -2255,11 +2256,61 @@ mod _sqlite {
|
||||
Self::expect_write(blob_len, 1, index, vm)?;
|
||||
let ret = inner.blob.write_single(value, index);
|
||||
self.check(ret, vm)
|
||||
} else if let Some(_slice) = needle.downcast_ref::<PySlice>() {
|
||||
Err(vm.new_not_implemented_error("Blob slice assignment is not implemented"))
|
||||
// let blob_len = inner.blob.bytes();
|
||||
// let slice = slice.to_saturated(vm)?;
|
||||
// let (range, step, length) = slice.adjust_indices(blob_len as usize);
|
||||
} else if let Some(slice) = needle.downcast_ref::<PySlice>() {
|
||||
// Handle slice assignment: blob[a:b:c] = b"..."
|
||||
let value_buf = PyBuffer::try_from_borrowed_object(vm, &value)?;
|
||||
|
||||
let buf = value_buf
|
||||
.as_contiguous()
|
||||
.ok_or_else(|| vm.new_buffer_error("underlying buffer is not C-contiguous"))?;
|
||||
|
||||
let blob_len = inner.blob.bytes();
|
||||
let slice = slice.to_saturated(vm)?;
|
||||
let (range, step, slice_len) = slice.adjust_indices(blob_len as usize);
|
||||
|
||||
if step == 0 {
|
||||
return Err(vm.new_value_error("slice step cannot be zero"));
|
||||
}
|
||||
|
||||
if buf.len() != slice_len {
|
||||
return Err(vm.new_index_error("Blob slice assignment is wrong size"));
|
||||
}
|
||||
|
||||
if slice_len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if step == 1 {
|
||||
let ret = inner.blob.write(
|
||||
buf.as_ptr().cast(),
|
||||
buf.len() as c_int,
|
||||
range.start as c_int,
|
||||
);
|
||||
self.check(ret, vm)
|
||||
} else {
|
||||
let span_len = range.end - range.start;
|
||||
let mut temp_buf = vec![0u8; span_len];
|
||||
|
||||
let ret = inner.blob.read(
|
||||
temp_buf.as_mut_ptr().cast(),
|
||||
span_len as c_int,
|
||||
range.start as c_int,
|
||||
);
|
||||
self.check(ret, vm)?;
|
||||
|
||||
let mut i_in_temp: usize = 0;
|
||||
for i_in_src in 0..slice_len {
|
||||
temp_buf[i_in_temp] = buf[i_in_src];
|
||||
i_in_temp += step as usize;
|
||||
}
|
||||
|
||||
let ret = inner.blob.write(
|
||||
temp_buf.as_ptr().cast(),
|
||||
span_len as c_int,
|
||||
range.start as c_int,
|
||||
);
|
||||
self.check(ret, vm)
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error("Blob indices must be integers"))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user