Skip to content

Commit 1d2d8ea

Browse files
committed
BytesIO getbuffer; no more hack for pickle.py
1 parent 8a539d0 commit 1d2d8ea

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

Lib/pickle.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ def commit_frame(self, force=False):
218218
if self.current_frame:
219219
f = self.current_frame
220220
if f.tell() >= self._FRAME_SIZE_TARGET or force:
221-
# data = f.getbuffer()
222-
data = f.getvalue()
221+
data = f.getbuffer()
223222
write = self.file_write
224223
if len(data) >= self._FRAME_SIZE_MIN:
225224
# Issue a single call to the write method of the underlying

Lib/test/test_memoryview.py

-2
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,6 @@ def test_release(self):
309309
m.release()
310310
self._check_released(m, tp)
311311

312-
# TODO: RUSTPYTHON
313-
@unittest.expectedFailure
314312
def test_writable_readonly(self):
315313
# Issue #10451: memoryview incorrectly exposes a readonly
316314
# buffer as writable causing a segfault if using mmap

vm/src/stdlib/io.rs

+62-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ mod _io {
1818
use std::io::{self, prelude::*, Cursor, SeekFrom};
1919

2020
use crate::byteslike::{PyBytesLike, PyRwBytesLike};
21-
use crate::common::cell::{PyRwLock, PyRwLockWriteGuard};
21+
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
22+
use crate::common::cell::{
23+
PyRwLock, PyRwLockReadGuard, PyRwLockUpgradableReadGuard, PyRwLockWriteGuard,
24+
};
2225
use crate::exceptions::{IntoPyException, PyBaseExceptionRef};
2326
use crate::function::{Args, KwArgs, OptionalArg, OptionalOption, PyFuncArgs};
2427
use crate::obj::objbool;
2528
use crate::obj::objbytearray::PyByteArray;
2629
use crate::obj::objbytes::PyBytesRef;
2730
use crate::obj::objint;
2831
use crate::obj::objiter;
32+
use crate::obj::objmemory::{Buffer, BufferOptions, BufferRef, PyMemoryView, PyMemoryViewRef};
2933
use crate::obj::objstr::{self, PyStr, PyStrRef};
3034
use crate::obj::objtype::{self, PyTypeRef};
3135
use crate::pyobject::{
@@ -939,6 +943,8 @@ mod _io {
939943
struct BytesIO {
940944
buffer: PyRwLock<BufferedIO>,
941945
closed: AtomicCell<bool>,
946+
exports: AtomicCell<usize>,
947+
buffer_options: PyRwLock<Option<Box<BufferOptions>>>,
942948
}
943949

944950
type BytesIORef = PyRef<BytesIO>;
@@ -972,6 +978,8 @@ mod _io {
972978
BytesIO {
973979
buffer: PyRwLock::new(BufferedIO::new(Cursor::new(raw_bytes))),
974980
closed: AtomicCell::new(false),
981+
exports: AtomicCell::new(0),
982+
buffer_options: PyRwLock::new(None),
975983
}
976984
.into_ref_with_type(vm, cls)
977985
}
@@ -981,6 +989,7 @@ mod _io {
981989
impl BytesIORef {
982990
#[pymethod]
983991
fn write(self, data: PyBytesLike, vm: &VirtualMachine) -> PyResult<u64> {
992+
self.try_resizable(vm)?;
984993
let mut buffer = self.buffer(vm)?;
985994
match data.with_ref(|b| buffer.write(b)) {
986995
Some(value) => Ok(value),
@@ -1048,6 +1057,7 @@ mod _io {
10481057

10491058
#[pymethod]
10501059
fn truncate(self, pos: OptionalSize, vm: &VirtualMachine) -> PyResult<()> {
1060+
self.try_resizable(vm)?;
10511061
let mut buffer = self.buffer(vm)?;
10521062
buffer.truncate(pos.try_usize(vm)?)?;
10531063
Ok(())
@@ -1059,8 +1069,57 @@ mod _io {
10591069
}
10601070

10611071
#[pymethod]
1062-
fn close(self) {
1063-
self.closed.store(true)
1072+
fn close(self, vm: &VirtualMachine) -> PyResult<()> {
1073+
self.try_resizable(vm)?;
1074+
self.closed.store(true);
1075+
Ok(())
1076+
}
1077+
1078+
#[pymethod]
1079+
fn getbuffer(self, vm: &VirtualMachine) -> PyResult<PyMemoryViewRef> {
1080+
let buffer: Box<dyn Buffer> = Box::new(self.clone());
1081+
let buffer = BufferRef::from(buffer);
1082+
let view = PyMemoryView::from_buffer(self.clone().into_object(), buffer, vm)?;
1083+
self.exports.fetch_add(1);
1084+
Ok(view.into_ref(vm))
1085+
}
1086+
}
1087+
1088+
impl Buffer for BytesIORef {
1089+
fn get_options(&self) -> BorrowedValue<BufferOptions> {
1090+
let guard = self.buffer_options.upgradable_read();
1091+
let guard = if guard.is_none() {
1092+
let mut w = PyRwLockUpgradableReadGuard::upgrade(guard);
1093+
*w = Some(Box::new(BufferOptions {
1094+
readonly: false,
1095+
len: self.buffer.read().cursor.get_ref().len(),
1096+
..Default::default()
1097+
}));
1098+
PyRwLockWriteGuard::downgrade(w)
1099+
} else {
1100+
PyRwLockUpgradableReadGuard::downgrade(guard)
1101+
};
1102+
PyRwLockReadGuard::map(guard, |x| x.as_ref().unwrap().as_ref()).into()
1103+
}
1104+
1105+
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
1106+
PyRwLockReadGuard::map(self.buffer.read(), |x| x.cursor.get_ref().as_slice()).into()
1107+
}
1108+
1109+
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
1110+
PyRwLockWriteGuard::map(self.buffer.write(), |x| x.cursor.get_mut().as_mut_slice())
1111+
.into()
1112+
}
1113+
1114+
fn release(&self) {
1115+
let mut w = self.buffer_options.write();
1116+
if self.exports.fetch_sub(1) == 1 {
1117+
*w = None;
1118+
}
1119+
}
1120+
1121+
fn is_resizable(&self) -> bool {
1122+
self.exports.load() == 0
10641123
}
10651124
}
10661125

0 commit comments

Comments
 (0)