Merge pull request #3391 from deantvv/os-error-refactor

Refactor OSError
This commit is contained in:
Jeong YunWon
2021-10-30 22:40:10 +09:00
committed by GitHub
6 changed files with 50 additions and 72 deletions

View File

@@ -178,8 +178,6 @@ class FinderTests(abc.FinderTests):
found = self._find(finder, 'doesnotexist')
self.assertEqual(found, self.NOT_FOUND)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_ignore_file(self):
# If a directory got changed to a file from underneath us, then don't
# worry about looking for submodules.

View File

@@ -734,8 +734,6 @@ class TestShutil(unittest.TestCase):
self.assertFalse(shutil._use_fd_functions)
self.assertFalse(shutil.rmtree.avoids_symlink_attacks)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_rmtree_dont_delete_file(self):
# When called on a file instead of a directory, don't delete it.
handle, path = tempfile.mkstemp()

View File

@@ -1395,8 +1395,6 @@ class ProcessTestCase(BaseTestCase):
self.assertFalse(os.path.exists(ofname))
self.assertFalse(os.path.exists(efname))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_communicate_epipe(self):
# Issue 10963: communicate() should hide EPIPE
p = subprocess.Popen(ZERO_RETURN_CMD,
@@ -1409,7 +1407,9 @@ class ProcessTestCase(BaseTestCase):
p.communicate(b"x" * 2**20)
# TODO: RUSTPYTHON
@unittest.expectedFailure
if sys.platform == "win32":
test_communicate_epipe = unittest.expectedFailure(test_communicate_epipe)
def test_communicate_epipe_only_stdin(self):
# Issue 10963: communicate() should hide EPIPE
p = subprocess.Popen(ZERO_RETURN_CMD,
@@ -1418,6 +1418,10 @@ class ProcessTestCase(BaseTestCase):
p.wait()
p.communicate(b"x" * 2**20)
# TODO: RUSTPYTHON
if sys.platform == "win32":
test_communicate_epipe_only_stdin = unittest.expectedFailure(test_communicate_epipe_only_stdin)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'),
@@ -2753,8 +2757,6 @@ class POSIXProcessTestCase(BaseTestCase):
stderr=inout, stdin=inout)
p.wait()
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_wait_when_sigchild_ignored(self):
# NOTE: sigchild_ignore.py may not be an effective test on all OSes.
sigchild_ignore = support.findfile("sigchild_ignore.py",

View File

@@ -358,10 +358,6 @@ class TestBadTempdir:
with self.assertRaises((NotADirectoryError, FileNotFoundError)):
self.make_temp()
# TODO: RUSTPYTHON
if sys.platform != "win32":
test_non_directory = unittest.expectedFailure(test_non_directory)
class TestMkstempInner(TestBadTempdir, BaseTestCase):
"""Test the internal function _mkstemp_inner."""
@@ -1503,10 +1499,6 @@ class TestTemporaryDirectory(BaseTestCase):
d.cleanup()
self.assertFalse(os.path.exists(d.name))
# TODO: RUSTPYTHON
if sys.platform not in {"darwin", "win32"}:
test_modes = unittest.expectedFailure(test_modes)
@unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.lchflags')
def test_flags(self):
flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK

View File

@@ -958,6 +958,33 @@ impl<C: widestring::UChar> IntoPyException for widestring::NulError<C> {
}
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn raw_os_error_to_exc_type(errno: i32, vm: &VirtualMachine) -> Option<PyTypeRef> {
use crate::stdlib::errno::errors;
let excs = &vm.ctx.exceptions;
match errno {
errors::EWOULDBLOCK => Some(excs.blocking_io_error.clone()),
errors::EALREADY => Some(excs.blocking_io_error.clone()),
errors::EINPROGRESS => Some(excs.blocking_io_error.clone()),
errors::EPIPE => Some(excs.broken_pipe_error.clone()),
errors::ESHUTDOWN => Some(excs.broken_pipe_error.clone()),
errors::ECHILD => Some(excs.child_process_error.clone()),
errors::ECONNABORTED => Some(excs.connection_aborted_error.clone()),
errors::ECONNREFUSED => Some(excs.connection_refused_error.clone()),
errors::ECONNRESET => Some(excs.connection_reset_error.clone()),
errors::EEXIST => Some(excs.file_exists_error.clone()),
errors::ENOENT => Some(excs.file_not_found_error.clone()),
errors::EISDIR => Some(excs.is_a_directory_error.clone()),
errors::ENOTDIR => Some(excs.not_a_directory_error.clone()),
errors::EINTR => Some(excs.interrupted_error.clone()),
errors::EACCES => Some(excs.permission_error.clone()),
errors::EPERM => Some(excs.permission_error.clone()),
errors::ESRCH => Some(excs.process_lookup_error.clone()),
errors::ETIMEDOUT => Some(excs.timeout_error.clone()),
_ => None,
}
}
pub(super) mod types {
use crate::common::lock::PyRwLock;
#[cfg_attr(target_os = "wasi", allow(unused_imports))]
@@ -1168,51 +1195,16 @@ pub(super) mod types {
fn os_error_optional_new(
args: Vec<PyObjectRef>,
vm: &VirtualMachine,
) -> Option<PyResult<PyBaseExceptionRef>> {
use crate::stdlib::errno::errors;
) -> Option<PyBaseExceptionRef> {
let len = args.len();
if len >= 2 {
let args = args.as_slice();
let errno = &args[0];
let error = match errno.payload_if_subclass::<PyInt>(vm) {
Some(errno) => match errno.try_to_primitive::<i32>(vm) {
Ok(errno) => {
let excs = &vm.ctx.exceptions;
let error = match errno {
errors::EWOULDBLOCK => Some(excs.blocking_io_error.clone()),
errors::EALREADY => Some(excs.blocking_io_error.clone()),
errors::EINPROGRESS => Some(excs.blocking_io_error.clone()),
errors::EPIPE => Some(excs.broken_pipe_error.clone()),
errors::ESHUTDOWN => Some(excs.broken_pipe_error.clone()),
errors::ECHILD => Some(excs.child_process_error.clone()),
errors::ECONNABORTED => Some(excs.connection_aborted_error.clone()),
errors::ECONNREFUSED => Some(excs.connection_refused_error.clone()),
errors::ECONNRESET => Some(excs.connection_reset_error.clone()),
errors::EEXIST => Some(excs.file_exists_error.clone()),
errors::ENOENT => Some(excs.file_not_found_error.clone()),
errors::EISDIR => Some(excs.is_a_directory_error.clone()),
errors::ENOTDIR => Some(excs.not_a_directory_error.clone()),
errors::EINTR => Some(excs.interrupted_error.clone()),
errors::EACCES => Some(excs.permission_error.clone()),
errors::EPERM => Some(excs.permission_error.clone()),
errors::ESRCH => Some(excs.process_lookup_error.clone()),
errors::ETIMEDOUT => Some(excs.timeout_error.clone()),
_ => None,
};
if error.is_some() {
Some(vm.invoke_exception(error?, args.to_vec()))
} else {
None
}
}
Err(_) => None,
},
None => None,
};
error
errno
.payload_if_subclass::<PyInt>(vm)
.and_then(|errno| errno.try_to_primitive::<i32>(vm).ok())
.and_then(|errno| super::raw_os_error_to_exc_type(errno, vm))
.and_then(|typ| vm.invoke_exception(typ, args.to_vec()).ok())
} else {
None
}
@@ -1224,7 +1216,7 @@ pub(super) mod types {
// 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.unwrap().into_pyresult(vm),
Some(error) => error.into_pyresult(vm),
None => PyBaseException::slot_new(cls, args, vm),
}
} else {

View File

@@ -1,4 +1,3 @@
use super::errno::errors;
use crate::crt_fd::Fd;
use crate::{
builtins::{PyBaseExceptionRef, PyBytes, PyBytesRef, PyInt, PySet, PyStr, PyStrRef},
@@ -238,20 +237,17 @@ impl IntoPyException for io::Error {
}
impl IntoPyException for &'_ io::Error {
fn into_pyexception(self, vm: &VirtualMachine) -> PyBaseExceptionRef {
let excs = &vm.ctx.exceptions;
#[allow(unreachable_patterns)] // some errors are just aliases of each other
let exc_type = match self.kind() {
ErrorKind::NotFound => vm.ctx.exceptions.file_not_found_error.clone(),
ErrorKind::PermissionDenied => vm.ctx.exceptions.permission_error.clone(),
ErrorKind::AlreadyExists => vm.ctx.exceptions.file_exists_error.clone(),
ErrorKind::WouldBlock => vm.ctx.exceptions.blocking_io_error.clone(),
_ => match self.raw_os_error() {
Some(errors::EAGAIN)
| Some(errors::EALREADY)
| Some(errors::EWOULDBLOCK)
| Some(errors::EINPROGRESS) => vm.ctx.exceptions.blocking_io_error.clone(),
Some(errors::ESRCH) => vm.ctx.exceptions.process_lookup_error.clone(),
_ => vm.ctx.exceptions.os_error.clone(),
},
ErrorKind::NotFound => excs.file_not_found_error.clone(),
ErrorKind::PermissionDenied => excs.permission_error.clone(),
ErrorKind::AlreadyExists => excs.file_exists_error.clone(),
ErrorKind::WouldBlock => excs.blocking_io_error.clone(),
_ => self
.raw_os_error()
.and_then(|errno| crate::exceptions::raw_os_error_to_exc_type(errno, vm))
.unwrap_or_else(|| excs.os_error.clone()),
};
let errno = self.raw_os_error().into_pyobject(vm);
let msg = vm.ctx.new_str(self.to_string()).into();