Skip to content

Commit d577bb7

Browse files
Merge pull request RustPython#787 from palaviv/os-fd
Add os.{read,write,remove,unlink}
2 parents 1faa7fa + 04acfe2 commit d577bb7

File tree

3 files changed

+74
-3
lines changed

3 files changed

+74
-3
lines changed

tests/snippets/stdlib_os.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,36 @@
22

33
from testutils import assert_raises
44

5-
assert os.open('README.md', 0) > 0
5+
fd = os.open('README.md', 0)
6+
assert fd > 0
7+
8+
os.close(fd)
9+
assert_raises(OSError, lambda: os.read(fd, 10))
10+
11+
FNAME = "test_file_that_no_one_will_have_on_disk"
12+
CONTENT = b"testing"
13+
CONTENT2 = b"rustpython"
14+
CONTENT3 = b"BOYA"
15+
16+
class TestWithFile():
17+
def __enter__(self):
18+
open(FNAME, "wb")
19+
return FNAME
20+
21+
def __exit__(self, exc_type, exc_val, exc_tb):
22+
os.remove(FNAME)
23+
24+
25+
with TestWithFile() as fname:
26+
fd = os.open(fname, 1)
27+
assert os.write(fd, CONTENT2) == len(CONTENT2)
28+
assert os.write(fd, CONTENT3) == len(CONTENT3)
29+
os.close(fd)
30+
31+
fd = os.open(fname, 0)
32+
assert os.read(fd, len(CONTENT2)) == CONTENT2
33+
assert os.read(fd, len(CONTENT3)) == CONTENT3
34+
os.close(fd)
635

736

837
assert_raises(FileNotFoundError, lambda: os.open('DOES_NOT_EXIST', 0))

vm/src/obj/objbytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use super::objtype::PyClassRef;
1717
pub struct PyBytes {
1818
value: Vec<u8>,
1919
}
20-
type PyBytesRef = PyRef<PyBytes>;
20+
pub type PyBytesRef = PyRef<PyBytes>;
2121

2222
impl PyBytes {
2323
pub fn new(data: Vec<u8>) -> Self {

vm/src/stdlib/os.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
use std::fs;
12
use std::fs::File;
23
use std::fs::OpenOptions;
3-
use std::io::ErrorKind;
4+
use std::io::{ErrorKind, Read, Write};
45

56
use num_traits::cast::ToPrimitive;
67

78
use crate::function::PyFuncArgs;
9+
use crate::obj::objbytes::PyBytesRef;
810
use crate::obj::objint;
11+
use crate::obj::objint::PyIntRef;
912
use crate::obj::objstr;
13+
use crate::obj::objstr::PyStringRef;
1014
use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol};
1115
use crate::vm::VirtualMachine;
1216

@@ -113,6 +117,40 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
113117
Err(vm.new_os_error(msg))
114118
}
115119

120+
fn os_read(fd: PyIntRef, n: PyIntRef, vm: &VirtualMachine) -> PyResult {
121+
let mut buffer = vec![0u8; n.as_bigint().to_usize().unwrap()];
122+
let mut file = rust_file(fd.as_bigint().to_i64().unwrap());
123+
match file.read_exact(&mut buffer) {
124+
Ok(_) => (),
125+
Err(s) => return Err(vm.new_os_error(s.to_string())),
126+
};
127+
128+
// Avoid closing the fd
129+
raw_file_number(file);
130+
Ok(vm.ctx.new_bytes(buffer))
131+
}
132+
133+
fn os_write(fd: PyIntRef, data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
134+
let mut file = rust_file(fd.as_bigint().to_i64().unwrap());
135+
let written = match file.write(&data) {
136+
Ok(written) => written,
137+
Err(s) => return Err(vm.new_os_error(s.to_string())),
138+
};
139+
140+
// Avoid closing the fd
141+
raw_file_number(file);
142+
Ok(vm.ctx.new_int(written))
143+
}
144+
145+
fn os_remove(path: PyStringRef, vm: &VirtualMachine) -> PyResult {
146+
match fs::remove_file(&path.value) {
147+
Ok(_) => (),
148+
Err(s) => return Err(vm.new_os_error(s.to_string())),
149+
}
150+
151+
Ok(vm.get_none())
152+
}
153+
116154
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
117155
let ctx = &vm.ctx;
118156

@@ -126,6 +164,10 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
126164
"open" => ctx.new_rustfunc(os_open),
127165
"close" => ctx.new_rustfunc(os_close),
128166
"error" => ctx.new_rustfunc(os_error),
167+
"read" => ctx.new_rustfunc(os_read),
168+
"write" => ctx.new_rustfunc(os_write),
169+
"remove" => ctx.new_rustfunc(os_remove),
170+
"unlink" => ctx.new_rustfunc(os_remove),
129171
"name" => ctx.new_str(os_name),
130172
"O_RDONLY" => ctx.new_int(0),
131173
"O_WRONLY" => ctx.new_int(1),

0 commit comments

Comments
 (0)