From b38e2418fa2f0476fa66de7989ebe5c92b0b40af Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 15 Nov 2019 16:17:29 +0200 Subject: [PATCH 1/3] BytesIO write accept PyBytesLike --- tests/snippets/stdlib_io_bytesio.py | 12 ++++++++++++ vm/src/stdlib/io.rs | 9 +++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/snippets/stdlib_io_bytesio.py b/tests/snippets/stdlib_io_bytesio.py index f6f97e684..aa193dc9f 100644 --- a/tests/snippets/stdlib_io_bytesio.py +++ b/tests/snippets/stdlib_io_bytesio.py @@ -42,9 +42,21 @@ def test_04(): assert f.seek(0) == 0 assert f.read(4) == b'Test' +def test_05(): + """ + Tests that the write method accpets bytearray + """ + bytes_string = b'Test String 5' + + f = BytesIO() + f.write(bytearray(bytes_string)) + + assert f.getvalue() == bytes_string + if __name__ == "__main__": test_01() test_02() test_03() test_04() + test_05() diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index bee7e1d7f..fb59e0f06 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -11,6 +11,7 @@ use num_traits::ToPrimitive; use super::os; use crate::function::{OptionalArg, OptionalOption, PyFuncArgs}; use crate::obj::objbytearray::PyByteArray; +use crate::obj::objbyteinner::PyBytesLike; use crate::obj::objbytes; use crate::obj::objbytes::PyBytes; use crate::obj::objint::{self, PyIntRef}; @@ -173,11 +174,11 @@ impl PyValue for PyBytesIO { } impl PyBytesIORef { - fn write(self, data: objbytes::PyBytesRef, vm: &VirtualMachine) -> PyResult { - let bytes = data.get_value(); + fn write(self, data: PyBytesLike, vm: &VirtualMachine) -> PyResult { + let bytes = data.to_cow(); - match self.buffer.borrow_mut().write(bytes) { - Some(value) => Ok(vm.ctx.new_int(value)), + match self.buffer.borrow_mut().write(&bytes) { + Some(value) => Ok(value), None => Err(vm.new_type_error("Error Writing Bytes".to_string())), } } From 043413a7ee8731316fea57c4f4b7b3198ffc5da2 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 15 Nov 2019 16:32:10 +0200 Subject: [PATCH 2/3] Add tell method to BytesIO, StringIO --- tests/snippets/stdlib_io_bytesio.py | 2 ++ tests/snippets/stdlib_io_stringio.py | 2 ++ vm/src/stdlib/io.rs | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/snippets/stdlib_io_bytesio.py b/tests/snippets/stdlib_io_bytesio.py index aa193dc9f..736560cde 100644 --- a/tests/snippets/stdlib_io_bytesio.py +++ b/tests/snippets/stdlib_io_bytesio.py @@ -7,6 +7,7 @@ def test_01(): f = BytesIO() f.write(bytes_string) + assert f.tell() == len(bytes_string) assert f.getvalue() == bytes_string def test_02(): @@ -39,6 +40,7 @@ def test_04(): f = BytesIO(string) assert f.read(4) == b'Test' + assert f.tell() == 4 assert f.seek(0) == 0 assert f.read(4) == b'Test' diff --git a/tests/snippets/stdlib_io_stringio.py b/tests/snippets/stdlib_io_stringio.py index 0b4182527..9f71b2b42 100644 --- a/tests/snippets/stdlib_io_stringio.py +++ b/tests/snippets/stdlib_io_stringio.py @@ -10,6 +10,7 @@ def test_01(): f = StringIO() f.write(string) + assert f.tell() == len(string) assert f.getvalue() == string def test_02(): @@ -46,6 +47,7 @@ def test_04(): f = StringIO(string) assert f.read(4) == 'Test' + assert f.tell() == 4 assert f.seek(0) == 0 assert f.read(4) == 'Test' diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index fb59e0f06..e662d4415 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -82,6 +82,10 @@ impl BufferedIO { Some(buffer) } + + fn tell(&self) -> u64 { + self.cursor.position() + } } #[derive(Debug)] @@ -142,6 +146,10 @@ impl PyStringIORef { Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_string())), } } + + fn tell(self, _vm: &VirtualMachine) -> u64 { + self.buffer.borrow().tell() + } } fn string_io_new( @@ -208,6 +216,10 @@ impl PyBytesIORef { fn seekable(self, _vm: &VirtualMachine) -> bool { true } + + fn tell(self, _vm: &VirtualMachine) -> u64 { + self.buffer.borrow().tell() + } } fn bytes_io_new( @@ -721,7 +733,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "seekable" => ctx.new_rustfunc(PyStringIORef::seekable), "read" => ctx.new_rustfunc(PyStringIORef::read), "write" => ctx.new_rustfunc(PyStringIORef::write), - "getvalue" => ctx.new_rustfunc(PyStringIORef::getvalue) + "getvalue" => ctx.new_rustfunc(PyStringIORef::getvalue), + "tell" => ctx.new_rustfunc(PyStringIORef::tell), }); //BytesIO: in-memory bytes @@ -732,7 +745,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "seek" => ctx.new_rustfunc(PyBytesIORef::seek), "seekable" => ctx.new_rustfunc(PyBytesIORef::seekable), "write" => ctx.new_rustfunc(PyBytesIORef::write), - "getvalue" => ctx.new_rustfunc(PyBytesIORef::getvalue) + "getvalue" => ctx.new_rustfunc(PyBytesIORef::getvalue), + "tell" => ctx.new_rustfunc(PyBytesIORef::tell) }); py_module!(vm, "_io", { From 7b83e8ae7bb41831854522bf188881ea857457ca Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 15 Nov 2019 17:16:25 +0200 Subject: [PATCH 3/3] add readline to BytesIO and StringIO --- tests/snippets/stdlib_io_bytesio.py | 16 ++++++++++++++++ tests/snippets/stdlib_io_stringio.py | 14 ++++++++++++++ vm/src/stdlib/io.rs | 27 ++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/snippets/stdlib_io_bytesio.py b/tests/snippets/stdlib_io_bytesio.py index 736560cde..571444876 100644 --- a/tests/snippets/stdlib_io_bytesio.py +++ b/tests/snippets/stdlib_io_bytesio.py @@ -55,10 +55,26 @@ def test_05(): assert f.getvalue() == bytes_string + +def test_06(): + """ + Tests readline + """ + bytes_string = b'Test String 6\nnew line is here\nfinished' + + f = BytesIO(bytes_string) + + assert f.readline() == b'Test String 6\n' + assert f.readline() == b'new line is here\n' + assert f.readline() == b'finished' + assert f.readline() == b'' + + if __name__ == "__main__": test_01() test_02() test_03() test_04() test_05() + test_06() diff --git a/tests/snippets/stdlib_io_stringio.py b/tests/snippets/stdlib_io_stringio.py index 9f71b2b42..828f0506e 100644 --- a/tests/snippets/stdlib_io_stringio.py +++ b/tests/snippets/stdlib_io_stringio.py @@ -51,8 +51,22 @@ def test_04(): assert f.seek(0) == 0 assert f.read(4) == 'Test' +def test_05(): + """ + Tests readline + """ + string = 'Test String 6\nnew line is here\nfinished' + + f = StringIO(string) + + assert f.readline() == 'Test String 6\n' + assert f.readline() == 'new line is here\n' + assert f.readline() == 'finished' + assert f.readline() == '' + if __name__ == "__main__": test_01() test_02() test_03() test_04() + test_05() diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index e662d4415..87ab1dcd4 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -86,6 +86,15 @@ impl BufferedIO { fn tell(&self) -> u64 { self.cursor.position() } + + fn readline(&mut self) -> Option { + let mut buf = String::new(); + + match self.cursor.read_line(&mut buf) { + Ok(_) => Some(buf), + Err(_) => None, + } + } } #[derive(Debug)] @@ -150,6 +159,13 @@ impl PyStringIORef { fn tell(self, _vm: &VirtualMachine) -> u64 { self.buffer.borrow().tell() } + + fn readline(self, vm: &VirtualMachine) -> PyResult { + match self.buffer.borrow_mut().readline() { + Some(line) => Ok(line), + None => Err(vm.new_value_error("Error Performing Operation".to_string())), + } + } } fn string_io_new( @@ -220,6 +236,13 @@ impl PyBytesIORef { fn tell(self, _vm: &VirtualMachine) -> u64 { self.buffer.borrow().tell() } + + fn readline(self, vm: &VirtualMachine) -> PyResult> { + match self.buffer.borrow_mut().readline() { + Some(line) => Ok(line.as_bytes().to_vec()), + None => Err(vm.new_value_error("Error Performing Operation".to_string())), + } + } } fn bytes_io_new( @@ -735,6 +758,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "write" => ctx.new_rustfunc(PyStringIORef::write), "getvalue" => ctx.new_rustfunc(PyStringIORef::getvalue), "tell" => ctx.new_rustfunc(PyStringIORef::tell), + "readline" => ctx.new_rustfunc(PyStringIORef::readline), }); //BytesIO: in-memory bytes @@ -746,7 +770,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "seekable" => ctx.new_rustfunc(PyBytesIORef::seekable), "write" => ctx.new_rustfunc(PyBytesIORef::write), "getvalue" => ctx.new_rustfunc(PyBytesIORef::getvalue), - "tell" => ctx.new_rustfunc(PyBytesIORef::tell) + "tell" => ctx.new_rustfunc(PyBytesIORef::tell), + "readline" => ctx.new_rustfunc(PyBytesIORef::readline), }); py_module!(vm, "_io", {