From 37e7972dcd438dfd0e0305236e4a0bbbc66a99eb Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 5 Apr 2019 17:51:03 +0300 Subject: [PATCH 1/6] Add os.read --- tests/snippets/stdlib_os.py | 9 ++++++++- vm/src/stdlib/os.rs | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/snippets/stdlib_os.py b/tests/snippets/stdlib_os.py index ed9e91c70..d70050495 100644 --- a/tests/snippets/stdlib_os.py +++ b/tests/snippets/stdlib_os.py @@ -2,8 +2,15 @@ import os from testutils import assert_raises -assert os.open('README.md', 0) > 0 +fd = os.open('README.md', 0) +assert fd > 0 +assert len(os.read(fd, 10)) == 10 +assert len(os.read(fd, 5)) == 5 + +assert_raises(OSError, lambda: os.read(fd + 1, 10)) +os.close(fd) +assert_raises(OSError, lambda: os.read(fd, 10)) assert_raises(FileNotFoundError, lambda: os.open('DOES_NOT_EXIST', 0)) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 3f0f557f1..0f5762014 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,6 +1,6 @@ use std::fs::File; use std::fs::OpenOptions; -use std::io::ErrorKind; +use std::io::{ErrorKind, Read}; use num_traits::cast::ToPrimitive; @@ -113,6 +113,25 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Err(vm.new_os_error(msg)) } +fn os_read(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(fd, Some(vm.ctx.int_type())), (n, Some(vm.ctx.int_type()))] + ); + + let mut buffer = vec![0u8; objint::get_value(n).to_usize().unwrap()]; + let mut file = rust_file(objint::get_value(fd).to_i64().unwrap()); + match file.read_exact(&mut buffer) { + Ok(_) => (), + Err(s) => return Err(vm.new_os_error(s.to_string())), + }; + + // Avoid closing the fd + raw_file_number(file); + Ok(vm.ctx.new_bytes(buffer)) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -126,6 +145,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "open" => ctx.new_rustfunc(os_open), "close" => ctx.new_rustfunc(os_close), "error" => ctx.new_rustfunc(os_error), + "read" => ctx.new_rustfunc(os_read), "name" => ctx.new_str(os_name), "O_RDONLY" => ctx.new_int(0), "O_WRONLY" => ctx.new_int(1), From 28c3ef1ae3c8a867c52f4306bd81e7587b484bff Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 5 Apr 2019 19:17:36 +0300 Subject: [PATCH 2/6] Add os.write --- vm/src/stdlib/os.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 0f5762014..b7e4280e5 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,10 +1,11 @@ use std::fs::File; use std::fs::OpenOptions; -use std::io::{ErrorKind, Read}; +use std::io::{ErrorKind, Read, Write}; use num_traits::cast::ToPrimitive; use crate::function::PyFuncArgs; +use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objstr; use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol}; @@ -132,6 +133,27 @@ fn os_read(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_bytes(buffer)) } +fn os_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [ + (fd, Some(vm.ctx.int_type())), + (data, Some(vm.ctx.bytes_type())) + ] + ); + + let mut file = rust_file(objint::get_value(fd).to_i64().unwrap()); + let written = match file.write(&objbytes::get_value(&data)) { + Ok(written) => written, + Err(s) => return Err(vm.new_os_error(s.to_string())), + }; + + // Avoid closing the fd + raw_file_number(file); + Ok(vm.ctx.new_int(written)) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -146,6 +168,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "close" => ctx.new_rustfunc(os_close), "error" => ctx.new_rustfunc(os_error), "read" => ctx.new_rustfunc(os_read), + "write" => ctx.new_rustfunc(os_write), "name" => ctx.new_str(os_name), "O_RDONLY" => ctx.new_int(0), "O_WRONLY" => ctx.new_int(1), From 1f19951ece36d1e229f0054abacdcfa4a2cf0907 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 5 Apr 2019 19:43:46 +0300 Subject: [PATCH 3/6] Add os.{remove,unlink} --- vm/src/stdlib/os.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index b7e4280e5..cd4c0709b 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,3 +1,4 @@ +use std::fs; use std::fs::File; use std::fs::OpenOptions; use std::io::{ErrorKind, Read, Write}; @@ -154,6 +155,18 @@ fn os_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_int(written)) } +fn os_remove(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(path, Some(vm.ctx.str_type()))]); + let fname = objstr::get_value(&path); + + match fs::remove_file(fname) { + Ok(_) => (), + Err(s) => return Err(vm.new_os_error(s.to_string())), + } + + Ok(vm.get_none()) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -169,6 +182,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "error" => ctx.new_rustfunc(os_error), "read" => ctx.new_rustfunc(os_read), "write" => ctx.new_rustfunc(os_write), + "remove" => ctx.new_rustfunc(os_remove), + "unlink" => ctx.new_rustfunc(os_remove), "name" => ctx.new_str(os_name), "O_RDONLY" => ctx.new_int(0), "O_WRONLY" => ctx.new_int(1), From cdd39bc50e7054b6ffbb9e12245b2e5140e59d83 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 5 Apr 2019 19:44:09 +0300 Subject: [PATCH 4/6] Add tests for os.{read, write} --- tests/snippets/stdlib_os.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/tests/snippets/stdlib_os.py b/tests/snippets/stdlib_os.py index d70050495..29c8005dc 100644 --- a/tests/snippets/stdlib_os.py +++ b/tests/snippets/stdlib_os.py @@ -5,13 +5,36 @@ from testutils import assert_raises fd = os.open('README.md', 0) assert fd > 0 -assert len(os.read(fd, 10)) == 10 -assert len(os.read(fd, 5)) == 5 - assert_raises(OSError, lambda: os.read(fd + 1, 10)) os.close(fd) assert_raises(OSError, lambda: os.read(fd, 10)) +FNAME = "test_file_that_no_one_will_have_on_disk" +CONTENT = b"testing" +CONTENT2 = b"rustpython" +CONTENT3 = b"BOYA" + +class TestWithFile(): + def __enter__(self): + open(FNAME, "wb") + return FNAME + + def __exit__(self, exc_type, exc_val, exc_tb): + os.remove(FNAME) + + +with TestWithFile() as fname: + fd = os.open(fname, 1) + assert os.write(fd, CONTENT2) == len(CONTENT2) + assert os.write(fd, CONTENT3) == len(CONTENT3) + os.close(fd) + + fd = os.open(fname, 0) + assert os.read(fd, len(CONTENT2)) == CONTENT2 + assert os.read(fd, len(CONTENT3)) == CONTENT3 + os.close(fd) + + assert_raises(FileNotFoundError, lambda: os.open('DOES_NOT_EXIST', 0)) From 1f0fd39722e63468884ee4b89947b97c89d40657 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Sat, 6 Apr 2019 17:29:40 +0300 Subject: [PATCH 5/6] Change os new funcs to new arg style --- vm/src/obj/objbytes.rs | 2 +- vm/src/stdlib/os.rs | 38 +++++++++++--------------------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index f24c9273c..4a8b1ad5e 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -17,7 +17,7 @@ use super::objtype::PyClassRef; pub struct PyBytes { value: Vec, } -type PyBytesRef = PyRef; +pub type PyBytesRef = PyRef; impl PyBytes { pub fn new(data: Vec) -> Self { diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index cd4c0709b..ae487598a 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -6,9 +6,11 @@ use std::io::{ErrorKind, Read, Write}; use num_traits::cast::ToPrimitive; use crate::function::PyFuncArgs; -use crate::obj::objbytes; +use crate::obj::objbytes::PyBytesRef; use crate::obj::objint; +use crate::obj::objint::PyIntRef; use crate::obj::objstr; +use crate::obj::objstr::PyStringRef; use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; @@ -115,15 +117,9 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Err(vm.new_os_error(msg)) } -fn os_read(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(fd, Some(vm.ctx.int_type())), (n, Some(vm.ctx.int_type()))] - ); - - let mut buffer = vec![0u8; objint::get_value(n).to_usize().unwrap()]; - let mut file = rust_file(objint::get_value(fd).to_i64().unwrap()); +fn os_read(fd: PyIntRef, n: PyIntRef, vm: &VirtualMachine) -> PyResult { + let mut buffer = vec![0u8; n.as_bigint().to_usize().unwrap()]; + let mut file = rust_file(fd.as_bigint().to_i64().unwrap()); match file.read_exact(&mut buffer) { Ok(_) => (), Err(s) => return Err(vm.new_os_error(s.to_string())), @@ -134,18 +130,9 @@ fn os_read(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_bytes(buffer)) } -fn os_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (fd, Some(vm.ctx.int_type())), - (data, Some(vm.ctx.bytes_type())) - ] - ); - - let mut file = rust_file(objint::get_value(fd).to_i64().unwrap()); - let written = match file.write(&objbytes::get_value(&data)) { +fn os_write(fd: PyIntRef, data: PyBytesRef, vm: &VirtualMachine) -> PyResult { + let mut file = rust_file(fd.as_bigint().to_i64().unwrap()); + let written = match file.write(&data) { Ok(written) => written, Err(s) => return Err(vm.new_os_error(s.to_string())), }; @@ -155,11 +142,8 @@ fn os_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_int(written)) } -fn os_remove(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(path, Some(vm.ctx.str_type()))]); - let fname = objstr::get_value(&path); - - match fs::remove_file(fname) { +fn os_remove(path: PyStringRef, vm: &VirtualMachine) -> PyResult { + match fs::remove_file(&path.value) { Ok(_) => (), Err(s) => return Err(vm.new_os_error(s.to_string())), } From 04acfe266523139f793e31e9cf148ab9374d27fe Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Sat, 6 Apr 2019 17:29:52 +0300 Subject: [PATCH 6/6] Remove failing line in windows --- tests/snippets/stdlib_os.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/snippets/stdlib_os.py b/tests/snippets/stdlib_os.py index 29c8005dc..ba6033ff8 100644 --- a/tests/snippets/stdlib_os.py +++ b/tests/snippets/stdlib_os.py @@ -5,7 +5,6 @@ from testutils import assert_raises fd = os.open('README.md', 0) assert fd > 0 -assert_raises(OSError, lambda: os.read(fd + 1, 10)) os.close(fd) assert_raises(OSError, lambda: os.read(fd, 10))