Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_exception_hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ def test_windows_error(self):
else:
self.assertNotIn('winerror', dir(OSError))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_posix_error(self):
e = OSError(EEXIST, "File already exists", "foo.txt")
self.assertEqual(e.errno, EEXIST)
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_fileio.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,6 @@ class PyAutoFileTests(AutoFileTests, unittest.TestCase):
FileIO = _pyio.FileIO
modulename = '_pyio'

# TODO: RUSTPYTHON
@unittest.expectedFailure
def testOpendir(self):
super().testOpendir()

Expand Down
6 changes: 0 additions & 6 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -1745,8 +1745,6 @@ def _seekrel(bufio):
def test_writes_and_truncates(self):
self.check_writes(lambda bufio: bufio.truncate(bufio.tell()))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_write_non_blocking(self):
raw = self.MockNonBlockWriterIO()
bufio = self.tp(raw, 8)
Expand Down Expand Up @@ -4346,13 +4344,9 @@ def test_pickling(self):
with self.open(os_helper.TESTFN, **kwargs) as f:
self.assertRaises(TypeError, pickle.dumps, f, protocol)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nonblock_pipe_write_bigbuf(self):
self._test_nonblock_pipe_write(16*1024)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nonblock_pipe_write_smallbuf(self):
self._test_nonblock_pipe_write(1024)

Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -1549,8 +1549,6 @@ def test_failed_child_execute_fd_leak(self):
fds_after_exception = os.listdir(fd_directory)
self.assertEqual(fds_before_popen, fds_after_exception)

# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skipIf(mswindows, "behavior currently not supported on Windows")
def test_file_not_found_includes_filename(self):
with self.assertRaises(FileNotFoundError) as c:
Expand Down
87 changes: 71 additions & 16 deletions vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ pub(super) mod types {
builtins::{traceback::PyTracebackRef, PyInt, PyTupleRef, PyTypeRef},
convert::ToPyResult,
function::FuncArgs,
PyObjectRef, PyRef, PyResult, VirtualMachine,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use crossbeam_utils::atomic::AtomicCell;
#[cfg_attr(target_arch = "wasm32", allow(unused_imports))]
Expand Down Expand Up @@ -1240,8 +1240,9 @@ pub(super) mod types {
os_error,
"Base class for I/O related errors.",
os_error_new,
base_exception_init,
os_error_init,
}

#[cfg(not(target_arch = "wasm32"))]
fn os_error_optional_new(
args: Vec<PyObjectRef>,
Expand All @@ -1261,25 +1262,78 @@ pub(super) mod types {
}
#[cfg(not(target_arch = "wasm32"))]
fn os_error_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
// We need this method, because of how `CPython` copies `init`
// from `BaseException` in `SimpleExtendsException` macro.
// See: `BaseException_new`
if cls.name().deref() == vm.ctx.exceptions.os_error.name().deref() {
match os_error_optional_new(args.args.to_vec(), vm) {
Some(error) => error.to_pyresult(vm),
None => PyBaseException::slot_new(cls, args, vm),
}
} else {
PyBaseException::slot_new(cls, args, vm)
}
let exc_self: PyBaseExceptionRef =
if cls.name().deref() == vm.ctx.exceptions.os_error.name().deref() {
match os_error_optional_new(args.args.to_vec(), vm) {
Some(error) => error,
None => PyBaseException::new(args.args.to_vec(), vm)
.into_ref_with_type(vm, cls)
.unwrap(),
}
} else {
PyBaseException::new(args.args.to_vec(), vm)
.into_ref_with_type(vm, cls)
.unwrap()
};

os_error_parse_args(&exc_self, &args, vm)?;
exc_self.to_pyresult(vm)
}
#[cfg(target_arch = "wasm32")]
fn os_error_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyBaseException::slot_new(cls, args, vm)
let exc_self = PyBaseException::new(args.args.to_vec(), vm)
.into_ref_with_type(vm, cls)
.unwrap();
os_error_parse_args(&exc_self, &args, vm)?;
exc_self.into_pyresult(vm)
}

fn base_exception_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
PyBaseException::init(zelf, args, vm)
fn os_error_parse_args(
exc_self: &PyBaseExceptionRef,
args: &FuncArgs,
vm: &VirtualMachine,
) -> PyResult<()> {
os_error_set_attr(exc_self, args, vm, "errno", 0)?;
os_error_set_attr(exc_self, args, vm, "strerror", 1)?;

os_error_set_attr(exc_self, args, vm, "filename", 2)?;
#[cfg(windows)]
os_error_set_attr(exc_self, args, vm, "winerror", 3)?;
os_error_set_attr(exc_self, args, vm, "filename2", 4)?;
Ok(())
}

fn os_error_set_attr(
exc_self: &PyBaseExceptionRef,
args: &FuncArgs,
vm: &VirtualMachine,
attr_name: &str,
arg_idx: usize,
) -> PyResult<()> {
let exc_self = exc_self.as_object();

if let Some(arg) = args.args.as_slice().get(arg_idx).cloned() {
exc_self.set_attr(attr_name, arg, vm)?;
} else {
exc_self.set_attr(attr_name, vm.ctx.none(), vm)?;
}

Ok(())
}

fn os_error_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
PyBaseException::init(zelf.clone(), args.clone(), vm)?;

let zelf: PyRef<PyBaseException> = zelf.try_into_value(vm)?;
if zelf.class().name().deref() == "BlockingIOError" {
os_error_set_attr(&zelf, &args, vm, "errno", 0)?;
os_error_set_attr(&zelf, &args, vm, "strerror", 1)?;
os_error_set_attr(&zelf, &args, vm, "characters_written", 2)?;
} else {
os_error_parse_args(&zelf, &args, vm)?;
}

Ok(())
}

define_exception! {
Expand All @@ -1288,6 +1342,7 @@ pub(super) mod types {
blocking_io_error,
"I/O operation would block."
}

define_exception! {
PyChildProcessError,
PyOSError,
Expand Down
10 changes: 8 additions & 2 deletions vm/src/stdlib/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ impl ToPyException for std::io::Error {
.unwrap_or(excs.os_error),
};
let errno = self.raw_os_error().to_pyobject(vm);
let msg = vm.ctx.new_str(self.to_string()).into();
vm.new_exception(exc_type.to_owned(), vec![errno, msg])
let msg: PyObjectRef = vm.ctx.new_str(self.to_string()).into();
if let Ok(exception) =
vm.invoke_exception(exc_type.to_owned(), vec![errno.clone(), msg.clone()])
{
exception
} else {
vm.new_exception(exc_type.to_owned(), vec![errno, msg])
}
}
}

Expand Down