Skip to content

Commit a59556a

Browse files
committed
Refactor OSError
Implement `raw_os_error_to_exc_type` to reduce duplication of errno to exception type.
1 parent a19e876 commit a59556a

File tree

6 files changed

+50
-72
lines changed

6 files changed

+50
-72
lines changed

Lib/test/test_importlib/source/test_finder.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,6 @@ def cleanup(tempdir):
178178
found = self._find(finder, 'doesnotexist')
179179
self.assertEqual(found, self.NOT_FOUND)
180180

181-
# TODO: RUSTPYTHON
182-
@unittest.expectedFailure
183181
def test_ignore_file(self):
184182
# If a directory got changed to a file from underneath us, then don't
185183
# worry about looking for submodules.

Lib/test/test_shutil.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,6 @@ def _raiser(*args, **kwargs):
734734
self.assertFalse(shutil._use_fd_functions)
735735
self.assertFalse(shutil.rmtree.avoids_symlink_attacks)
736736

737-
# TODO: RUSTPYTHON
738-
@unittest.expectedFailure
739737
def test_rmtree_dont_delete_file(self):
740738
# When called on a file instead of a directory, don't delete it.
741739
handle, path = tempfile.mkstemp()

Lib/test/test_subprocess.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,8 +1395,6 @@ def test_handles_closed_on_exception(self):
13951395
self.assertFalse(os.path.exists(ofname))
13961396
self.assertFalse(os.path.exists(efname))
13971397

1398-
# TODO: RUSTPYTHON
1399-
@unittest.expectedFailure
14001398
def test_communicate_epipe(self):
14011399
# Issue 10963: communicate() should hide EPIPE
14021400
p = subprocess.Popen(ZERO_RETURN_CMD,
@@ -1409,7 +1407,9 @@ def test_communicate_epipe(self):
14091407
p.communicate(b"x" * 2**20)
14101408

14111409
# TODO: RUSTPYTHON
1412-
@unittest.expectedFailure
1410+
if sys.platform == "win32":
1411+
test_communicate_epipe = unittest.expectedFailure(test_communicate_epipe)
1412+
14131413
def test_communicate_epipe_only_stdin(self):
14141414
# Issue 10963: communicate() should hide EPIPE
14151415
p = subprocess.Popen(ZERO_RETURN_CMD,
@@ -1418,6 +1418,10 @@ def test_communicate_epipe_only_stdin(self):
14181418
p.wait()
14191419
p.communicate(b"x" * 2**20)
14201420

1421+
# TODO: RUSTPYTHON
1422+
if sys.platform == "win32":
1423+
test_communicate_epipe_only_stdin = unittest.expectedFailure(test_communicate_epipe_only_stdin)
1424+
14211425
# TODO: RUSTPYTHON
14221426
@unittest.expectedFailure
14231427
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'),
@@ -2753,8 +2757,6 @@ def test_stderr_stdin_are_single_inout_fd(self):
27532757
stderr=inout, stdin=inout)
27542758
p.wait()
27552759

2756-
# TODO: RUSTPYTHON
2757-
@unittest.expectedFailure
27582760
def test_wait_when_sigchild_ignored(self):
27592761
# NOTE: sigchild_ignore.py may not be an effective test on all OSes.
27602762
sigchild_ignore = support.findfile("sigchild_ignore.py",

Lib/test/test_tempfile.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,6 @@ def test_non_directory(self):
358358
with self.assertRaises((NotADirectoryError, FileNotFoundError)):
359359
self.make_temp()
360360

361-
# TODO: RUSTPYTHON
362-
if sys.platform != "win32":
363-
test_non_directory = unittest.expectedFailure(test_non_directory)
364-
365361

366362
class TestMkstempInner(TestBadTempdir, BaseTestCase):
367363
"""Test the internal function _mkstemp_inner."""
@@ -1503,10 +1499,6 @@ def test_modes(self):
15031499
d.cleanup()
15041500
self.assertFalse(os.path.exists(d.name))
15051501

1506-
# TODO: RUSTPYTHON
1507-
if sys.platform not in {"darwin", "win32"}:
1508-
test_modes = unittest.expectedFailure(test_modes)
1509-
15101502
@unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.lchflags')
15111503
def test_flags(self):
15121504
flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK

vm/src/exceptions.rs

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,33 @@ impl<C: widestring::UChar> IntoPyException for widestring::NulError<C> {
958958
}
959959
}
960960

961+
#[cfg(not(target_arch = "wasm32"))]
962+
pub(crate) fn raw_os_error_to_exc_type(errno: i32, vm: &VirtualMachine) -> Option<PyTypeRef> {
963+
use crate::stdlib::errno::errors;
964+
let excs = &vm.ctx.exceptions;
965+
match errno {
966+
errors::EWOULDBLOCK => Some(excs.blocking_io_error.clone()),
967+
errors::EALREADY => Some(excs.blocking_io_error.clone()),
968+
errors::EINPROGRESS => Some(excs.blocking_io_error.clone()),
969+
errors::EPIPE => Some(excs.broken_pipe_error.clone()),
970+
errors::ESHUTDOWN => Some(excs.broken_pipe_error.clone()),
971+
errors::ECHILD => Some(excs.child_process_error.clone()),
972+
errors::ECONNABORTED => Some(excs.connection_aborted_error.clone()),
973+
errors::ECONNREFUSED => Some(excs.connection_refused_error.clone()),
974+
errors::ECONNRESET => Some(excs.connection_reset_error.clone()),
975+
errors::EEXIST => Some(excs.file_exists_error.clone()),
976+
errors::ENOENT => Some(excs.file_not_found_error.clone()),
977+
errors::EISDIR => Some(excs.is_a_directory_error.clone()),
978+
errors::ENOTDIR => Some(excs.not_a_directory_error.clone()),
979+
errors::EINTR => Some(excs.interrupted_error.clone()),
980+
errors::EACCES => Some(excs.permission_error.clone()),
981+
errors::EPERM => Some(excs.permission_error.clone()),
982+
errors::ESRCH => Some(excs.process_lookup_error.clone()),
983+
errors::ETIMEDOUT => Some(excs.timeout_error.clone()),
984+
_ => None,
985+
}
986+
}
987+
961988
pub(super) mod types {
962989
use crate::common::lock::PyRwLock;
963990
use crate::{
@@ -1166,51 +1193,16 @@ pub(super) mod types {
11661193
fn os_error_optional_new(
11671194
args: Vec<PyObjectRef>,
11681195
vm: &VirtualMachine,
1169-
) -> Option<PyResult<PyBaseExceptionRef>> {
1170-
use crate::stdlib::errno::errors;
1171-
1196+
) -> Option<PyBaseExceptionRef> {
11721197
let len = args.len();
11731198
if len >= 2 {
11741199
let args = args.as_slice();
11751200
let errno = &args[0];
1176-
let error = match errno.payload_if_subclass::<PyInt>(vm) {
1177-
Some(errno) => match errno.try_to_primitive::<i32>(vm) {
1178-
Ok(errno) => {
1179-
let excs = &vm.ctx.exceptions;
1180-
let error = match errno {
1181-
errors::EWOULDBLOCK => Some(excs.blocking_io_error.clone()),
1182-
errors::EALREADY => Some(excs.blocking_io_error.clone()),
1183-
errors::EINPROGRESS => Some(excs.blocking_io_error.clone()),
1184-
errors::EPIPE => Some(excs.broken_pipe_error.clone()),
1185-
errors::ESHUTDOWN => Some(excs.broken_pipe_error.clone()),
1186-
errors::ECHILD => Some(excs.child_process_error.clone()),
1187-
errors::ECONNABORTED => Some(excs.connection_aborted_error.clone()),
1188-
errors::ECONNREFUSED => Some(excs.connection_refused_error.clone()),
1189-
errors::ECONNRESET => Some(excs.connection_reset_error.clone()),
1190-
errors::EEXIST => Some(excs.file_exists_error.clone()),
1191-
errors::ENOENT => Some(excs.file_not_found_error.clone()),
1192-
errors::EISDIR => Some(excs.is_a_directory_error.clone()),
1193-
errors::ENOTDIR => Some(excs.not_a_directory_error.clone()),
1194-
errors::EINTR => Some(excs.interrupted_error.clone()),
1195-
errors::EACCES => Some(excs.permission_error.clone()),
1196-
errors::EPERM => Some(excs.permission_error.clone()),
1197-
errors::ESRCH => Some(excs.process_lookup_error.clone()),
1198-
errors::ETIMEDOUT => Some(excs.timeout_error.clone()),
1199-
_ => None,
1200-
};
1201-
1202-
if error.is_some() {
1203-
Some(vm.invoke_exception(error?, args.to_vec()))
1204-
} else {
1205-
None
1206-
}
1207-
}
1208-
Err(_) => None,
1209-
},
1210-
None => None,
1211-
};
1212-
1213-
error
1201+
errno
1202+
.payload_if_subclass::<PyInt>(vm)
1203+
.and_then(|errno| errno.try_to_primitive::<i32>(vm).ok())
1204+
.and_then(|errno| super::raw_os_error_to_exc_type(errno, vm))
1205+
.and_then(|typ| vm.invoke_exception(typ, args.to_vec()).ok())
12141206
} else {
12151207
None
12161208
}
@@ -1222,7 +1214,7 @@ pub(super) mod types {
12221214
// See: `BaseException_new`
12231215
if cls.name().deref() == vm.ctx.exceptions.os_error.name().deref() {
12241216
match os_error_optional_new(args.args.to_vec(), vm) {
1225-
Some(error) => error.unwrap().into_pyresult(vm),
1217+
Some(error) => error.into_pyresult(vm),
12261218
None => PyBaseException::slot_new(cls, args, vm),
12271219
}
12281220
} else {

vm/src/stdlib/os.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use super::errno::errors;
21
use crate::crt_fd::Fd;
32
use crate::{
43
builtins::{PyBaseExceptionRef, PyBytes, PyBytesRef, PyInt, PySet, PyStr, PyStrRef},
@@ -238,20 +237,17 @@ impl IntoPyException for io::Error {
238237
}
239238
impl IntoPyException for &'_ io::Error {
240239
fn into_pyexception(self, vm: &VirtualMachine) -> PyBaseExceptionRef {
240+
let excs = &vm.ctx.exceptions;
241241
#[allow(unreachable_patterns)] // some errors are just aliases of each other
242242
let exc_type = match self.kind() {
243-
ErrorKind::NotFound => vm.ctx.exceptions.file_not_found_error.clone(),
244-
ErrorKind::PermissionDenied => vm.ctx.exceptions.permission_error.clone(),
245-
ErrorKind::AlreadyExists => vm.ctx.exceptions.file_exists_error.clone(),
246-
ErrorKind::WouldBlock => vm.ctx.exceptions.blocking_io_error.clone(),
247-
_ => match self.raw_os_error() {
248-
Some(errors::EAGAIN)
249-
| Some(errors::EALREADY)
250-
| Some(errors::EWOULDBLOCK)
251-
| Some(errors::EINPROGRESS) => vm.ctx.exceptions.blocking_io_error.clone(),
252-
Some(errors::ESRCH) => vm.ctx.exceptions.process_lookup_error.clone(),
253-
_ => vm.ctx.exceptions.os_error.clone(),
254-
},
243+
ErrorKind::NotFound => excs.file_not_found_error.clone(),
244+
ErrorKind::PermissionDenied => excs.permission_error.clone(),
245+
ErrorKind::AlreadyExists => excs.file_exists_error.clone(),
246+
ErrorKind::WouldBlock => excs.blocking_io_error.clone(),
247+
_ => self
248+
.raw_os_error()
249+
.and_then(|errno| crate::exceptions::raw_os_error_to_exc_type(errno, vm))
250+
.unwrap_or_else(|| excs.os_error.clone()),
255251
};
256252
let errno = self.raw_os_error().into_pyobject(vm);
257253
let msg = vm.ctx.new_str(self.to_string()).into();

0 commit comments

Comments
 (0)