forked from Rust-related/RustPython
Move free functions in vm::exceptions to vm methods
This commit is contained in:
@@ -13,8 +13,8 @@ fn run(vm: &vm::VirtualMachine) -> vm::PyResult<()> {
|
||||
|
||||
let res = vm.run_code_obj(vm.new_code_object(module), scope);
|
||||
|
||||
if let Err(err) = res {
|
||||
vm::exceptions::print_exception(&vm, err);
|
||||
if let Err(exc) = res {
|
||||
vm.print_exception(exc);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -76,8 +76,8 @@ def fib(n):
|
||||
scope.globals.set_item("last", output, vm)?;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
vm::exceptions::print_exception(vm, e);
|
||||
Err(exc) => {
|
||||
vm.print_exception(exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/lib.rs
10
src/lib.rs
@@ -45,9 +45,9 @@ extern crate log;
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||
use rustpython_vm::{
|
||||
builtins::PyDictRef, builtins::PyInt, compile, exceptions::print_exception, match_class,
|
||||
scope::Scope, stdlib::sys, InitParameter, Interpreter, ItemProtocol, PyObjectRef, PyResult,
|
||||
PySettings, TryFromObject, TypeProtocol, VirtualMachine,
|
||||
builtins::PyDictRef, builtins::PyInt, compile, match_class, scope::Scope, stdlib::sys,
|
||||
InitParameter, Interpreter, ItemProtocol, PyObjectRef, PyResult, PySettings, TryFromObject,
|
||||
TypeProtocol, VirtualMachine,
|
||||
};
|
||||
|
||||
use std::convert::TryInto;
|
||||
@@ -136,8 +136,8 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
print_exception(vm, err);
|
||||
Err(exc) => {
|
||||
vm.print_exception(exc);
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ use rustpython_vm::readline::{Readline, ReadlineResult};
|
||||
use rustpython_vm::{
|
||||
builtins::PyBaseExceptionRef,
|
||||
compile::{self, CompileError, CompileErrorType},
|
||||
exceptions::print_exception,
|
||||
scope::Scope,
|
||||
PyResult, TypeProtocol, VirtualMachine,
|
||||
};
|
||||
@@ -130,7 +129,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
repl.save_history(&repl_history_path).unwrap();
|
||||
return Err(exc);
|
||||
}
|
||||
print_exception(vm, exc);
|
||||
vm.print_exception(exc);
|
||||
}
|
||||
}
|
||||
repl.save_history(&repl_history_path).unwrap();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
builtins::{PyBaseExceptionRef, PyStrRef},
|
||||
common::lock::PyMutex,
|
||||
exceptions,
|
||||
frame::{ExecutionResult, FrameRef},
|
||||
protocol::PyIterReturn,
|
||||
IdProtocol, PyObjectRef, PyResult, TypeProtocol, VirtualMachine,
|
||||
@@ -140,7 +139,7 @@ impl Coro {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyIterReturn> {
|
||||
if self.closed.load() {
|
||||
return Err(exceptions::normalize(exc_type, exc_val, exc_tb, vm)?);
|
||||
return Err(vm.normalize_exception(exc_type, exc_val, exc_tb)?);
|
||||
}
|
||||
let result = self.run_with_context(gen, vm, |f| f.gen_throw(vm, exc_type, exc_val, exc_tb));
|
||||
self.maybe_close(&result);
|
||||
|
||||
@@ -31,48 +31,175 @@ impl PyValue for PyBaseException {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chain<T>(e1: PyResult<()>, e2: PyResult<T>) -> PyResult<T> {
|
||||
match (e1, e2) {
|
||||
(Err(e1), Err(e)) => {
|
||||
e.set_context(Some(e1));
|
||||
Err(e)
|
||||
}
|
||||
(Err(e), Ok(_)) | (Ok(()), Err(e)) => Err(e),
|
||||
(Ok(()), Ok(close_res)) => Ok(close_res),
|
||||
}
|
||||
}
|
||||
impl VirtualMachine {
|
||||
// Why `impl VirtualMachine?
|
||||
// These functions are natively free function in CPython - not methods of PyException
|
||||
|
||||
/// Print exception chain by calling sys.excepthook
|
||||
pub fn print_exception(vm: &VirtualMachine, exc: PyBaseExceptionRef) {
|
||||
let write_fallback = |exc, errstr| {
|
||||
if let Ok(stderr) = sys::get_stderr(vm) {
|
||||
let mut stderr = py_io::PyWriter(stderr, vm);
|
||||
// if this fails stderr might be closed -- ignore it
|
||||
let _ = writeln!(stderr, "{}", errstr);
|
||||
let _ = write_exception(&mut stderr, vm, exc);
|
||||
/// Print exception chain by calling sys.excepthook
|
||||
pub fn print_exception(&self, exc: PyBaseExceptionRef) {
|
||||
let vm = self;
|
||||
let write_fallback = |exc, errstr| {
|
||||
if let Ok(stderr) = sys::get_stderr(vm) {
|
||||
let mut stderr = py_io::PyWriter(stderr, vm);
|
||||
// if this fails stderr might be closed -- ignore it
|
||||
let _ = writeln!(stderr, "{}", errstr);
|
||||
let _ = self.write_exception(&mut stderr, exc);
|
||||
} else {
|
||||
eprintln!("{}\nlost sys.stderr", errstr);
|
||||
let _ = self.write_exception(&mut py_io::IoWriter(io::stderr()), exc);
|
||||
}
|
||||
};
|
||||
if let Ok(excepthook) = vm.get_attribute(vm.sys_module.clone(), "excepthook") {
|
||||
let (exc_type, exc_val, exc_tb) = vm.split_exception(exc.clone());
|
||||
if let Err(eh_exc) = vm.invoke(&excepthook, vec![exc_type, exc_val, exc_tb]) {
|
||||
write_fallback(&eh_exc, "Error in sys.excepthook:");
|
||||
write_fallback(&exc, "Original exception was:");
|
||||
}
|
||||
} else {
|
||||
eprintln!("{}\nlost sys.stderr", errstr);
|
||||
let _ = write_exception(&mut py_io::IoWriter(io::stderr()), vm, exc);
|
||||
write_fallback(&exc, "missing sys.excepthook");
|
||||
}
|
||||
};
|
||||
if let Ok(excepthook) = vm.get_attribute(vm.sys_module.clone(), "excepthook") {
|
||||
let (exc_type, exc_val, exc_tb) = split(exc.clone(), vm);
|
||||
if let Err(eh_exc) = vm.invoke(&excepthook, vec![exc_type, exc_val, exc_tb]) {
|
||||
write_fallback(&eh_exc, "Error in sys.excepthook:");
|
||||
write_fallback(&exc, "Original exception was:");
|
||||
}
|
||||
} else {
|
||||
write_fallback(&exc, "missing sys.excepthook");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_exception<W: Write>(
|
||||
output: &mut W,
|
||||
vm: &VirtualMachine,
|
||||
exc: &PyBaseExceptionRef,
|
||||
) -> Result<(), W::Error> {
|
||||
let seen = &mut HashSet::<usize>::new();
|
||||
write_exception_recursive(output, vm, exc, seen)
|
||||
pub fn write_exception<W: Write>(
|
||||
&self,
|
||||
output: &mut W,
|
||||
exc: &PyBaseExceptionRef,
|
||||
) -> Result<(), W::Error> {
|
||||
let seen = &mut HashSet::<usize>::new();
|
||||
self.write_exception_recursive(output, exc, seen)
|
||||
}
|
||||
|
||||
fn write_exception_recursive<W: Write>(
|
||||
&self,
|
||||
output: &mut W,
|
||||
exc: &PyBaseExceptionRef,
|
||||
seen: &mut HashSet<usize>,
|
||||
) -> Result<(), W::Error> {
|
||||
// This function should not be called directly,
|
||||
// use `wite_exception` as a public interface.
|
||||
// It is similar to `print_exception_recursive` from `CPython`.
|
||||
seen.insert(exc.as_object().get_id());
|
||||
|
||||
#[allow(clippy::manual_map)]
|
||||
if let Some((cause_or_context, msg)) = if let Some(cause) = exc.cause() {
|
||||
// This can be a special case: `raise e from e`,
|
||||
// we just ignore it and treat like `raise e` without any extra steps.
|
||||
Some((
|
||||
cause,
|
||||
"\nThe above exception was the direct cause of the following exception:\n",
|
||||
))
|
||||
} else if let Some(context) = exc.context() {
|
||||
// This can be a special case:
|
||||
// e = ValueError('e')
|
||||
// e.__context__ = e
|
||||
// In this case, we just ignore
|
||||
// `__context__` part from going into recursion.
|
||||
Some((
|
||||
context,
|
||||
"\nDuring handling of the above exception, another exception occurred:\n",
|
||||
))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
if !seen.contains(&cause_or_context.as_object().get_id()) {
|
||||
self.write_exception_recursive(output, &cause_or_context, seen)?;
|
||||
writeln!(output, "{}", msg)?;
|
||||
} else {
|
||||
seen.insert(cause_or_context.as_object().get_id());
|
||||
}
|
||||
}
|
||||
|
||||
self.write_exception_inner(output, exc)
|
||||
}
|
||||
|
||||
/// Print exception with traceback
|
||||
pub fn write_exception_inner<W: Write>(
|
||||
&self,
|
||||
output: &mut W,
|
||||
exc: &PyBaseExceptionRef,
|
||||
) -> Result<(), W::Error> {
|
||||
let vm = self;
|
||||
if let Some(tb) = exc.traceback.read().clone() {
|
||||
writeln!(output, "Traceback (most recent call last):")?;
|
||||
for tb in tb.iter() {
|
||||
write_traceback_entry(output, &tb)?;
|
||||
}
|
||||
}
|
||||
|
||||
let varargs = exc.args();
|
||||
let args_repr = vm.exception_args_as_string(varargs, true);
|
||||
|
||||
let exc_type = exc.class();
|
||||
let exc_name = exc_type.name();
|
||||
match args_repr.len() {
|
||||
0 => writeln!(output, "{}", exc_name),
|
||||
1 => writeln!(output, "{}: {}", exc_name, args_repr[0]),
|
||||
_ => writeln!(
|
||||
output,
|
||||
"{}: ({})",
|
||||
exc_name,
|
||||
args_repr.into_iter().format(", ")
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn exception_args_as_string(&self, varargs: PyTupleRef, str_single: bool) -> Vec<PyStrRef> {
|
||||
let vm = self;
|
||||
let varargs = varargs.as_slice();
|
||||
match varargs.len() {
|
||||
0 => vec![],
|
||||
1 => {
|
||||
let args0_repr = if str_single {
|
||||
vm.to_str(&varargs[0])
|
||||
.unwrap_or_else(|_| PyStr::from("<element str() failed>").into_ref(vm))
|
||||
} else {
|
||||
vm.to_repr(&varargs[0])
|
||||
.unwrap_or_else(|_| PyStr::from("<element repr() failed>").into_ref(vm))
|
||||
};
|
||||
vec![args0_repr]
|
||||
}
|
||||
_ => varargs
|
||||
.iter()
|
||||
.map(|vararg| {
|
||||
vm.to_repr(vararg)
|
||||
.unwrap_or_else(|_| PyStr::from("<element repr() failed>").into_ref(vm))
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_exception(
|
||||
&self,
|
||||
exc: PyBaseExceptionRef,
|
||||
) -> (PyObjectRef, PyObjectRef, PyObjectRef) {
|
||||
let tb = exc.traceback().into_pyobject(self);
|
||||
(exc.clone_class().into(), exc.into(), tb)
|
||||
}
|
||||
|
||||
/// Similar to PyErr_NormalizeException in CPython
|
||||
pub fn normalize_exception(
|
||||
&self,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: PyObjectRef,
|
||||
exc_tb: PyObjectRef,
|
||||
) -> PyResult<PyBaseExceptionRef> {
|
||||
let ctor = ExceptionCtor::try_from_object(self, exc_type)?;
|
||||
let exc = ctor.instantiate_value(exc_val, self)?;
|
||||
if let Some(tb) = Option::<PyTracebackRef>::try_from_object(self, exc_tb)? {
|
||||
exc.set_traceback(Some(tb));
|
||||
}
|
||||
Ok(exc)
|
||||
}
|
||||
|
||||
pub fn invoke_exception(
|
||||
&self,
|
||||
cls: PyTypeRef,
|
||||
args: Vec<PyObjectRef>,
|
||||
) -> PyResult<PyBaseExceptionRef> {
|
||||
// TODO: fast-path built-in exceptions by directly instantiating them? Is that really worth it?
|
||||
let res = self.invoke(cls.as_object(), args)?;
|
||||
PyBaseExceptionRef::try_from_object(self, res)
|
||||
}
|
||||
}
|
||||
|
||||
fn print_source_line<W: Write>(
|
||||
@@ -117,107 +244,6 @@ fn write_traceback_entry<W: Write>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_exception_recursive<W: Write>(
|
||||
output: &mut W,
|
||||
vm: &VirtualMachine,
|
||||
exc: &PyBaseExceptionRef,
|
||||
seen: &mut HashSet<usize>,
|
||||
) -> Result<(), W::Error> {
|
||||
// This function should not be called directly,
|
||||
// use `wite_exception` as a public interface.
|
||||
// It is similar to `print_exception_recursive` from `CPython`.
|
||||
seen.insert(exc.as_object().get_id());
|
||||
|
||||
#[allow(clippy::manual_map)]
|
||||
if let Some((cause_or_context, msg)) = if let Some(cause) = exc.cause() {
|
||||
// This can be a special case: `raise e from e`,
|
||||
// we just ignore it and treat like `raise e` without any extra steps.
|
||||
Some((
|
||||
cause,
|
||||
"\nThe above exception was the direct cause of the following exception:\n",
|
||||
))
|
||||
} else if let Some(context) = exc.context() {
|
||||
// This can be a special case:
|
||||
// e = ValueError('e')
|
||||
// e.__context__ = e
|
||||
// In this case, we just ignore
|
||||
// `__context__` part from going into recursion.
|
||||
Some((
|
||||
context,
|
||||
"\nDuring handling of the above exception, another exception occurred:\n",
|
||||
))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
if !seen.contains(&cause_or_context.as_object().get_id()) {
|
||||
write_exception_recursive(output, vm, &cause_or_context, seen)?;
|
||||
writeln!(output, "{}", msg)?;
|
||||
} else {
|
||||
seen.insert(cause_or_context.as_object().get_id());
|
||||
}
|
||||
}
|
||||
|
||||
write_exception_inner(output, vm, exc)
|
||||
}
|
||||
|
||||
/// Print exception with traceback
|
||||
pub fn write_exception_inner<W: Write>(
|
||||
output: &mut W,
|
||||
vm: &VirtualMachine,
|
||||
exc: &PyBaseExceptionRef,
|
||||
) -> Result<(), W::Error> {
|
||||
if let Some(tb) = exc.traceback.read().clone() {
|
||||
writeln!(output, "Traceback (most recent call last):")?;
|
||||
for tb in tb.iter() {
|
||||
write_traceback_entry(output, &tb)?;
|
||||
}
|
||||
}
|
||||
|
||||
let varargs = exc.args();
|
||||
let args_repr = exception_args_as_string(vm, varargs, true);
|
||||
|
||||
let exc_class = exc.class();
|
||||
let exc_name = exc_class.name();
|
||||
match args_repr.len() {
|
||||
0 => writeln!(output, "{}", exc_name),
|
||||
1 => writeln!(output, "{}: {}", exc_name, args_repr[0]),
|
||||
_ => writeln!(
|
||||
output,
|
||||
"{}: ({})",
|
||||
exc_name,
|
||||
args_repr.into_iter().format(", ")
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn exception_args_as_string(
|
||||
vm: &VirtualMachine,
|
||||
varargs: PyTupleRef,
|
||||
str_single: bool,
|
||||
) -> Vec<PyStrRef> {
|
||||
let varargs = varargs.as_slice();
|
||||
match varargs.len() {
|
||||
0 => vec![],
|
||||
1 => {
|
||||
let args0_repr = if str_single {
|
||||
vm.to_str(&varargs[0])
|
||||
.unwrap_or_else(|_| PyStr::from("<element str() failed>").into_ref(vm))
|
||||
} else {
|
||||
vm.to_repr(&varargs[0])
|
||||
.unwrap_or_else(|_| PyStr::from("<element repr() failed>").into_ref(vm))
|
||||
};
|
||||
vec![args0_repr]
|
||||
}
|
||||
_ => varargs
|
||||
.iter()
|
||||
.map(|vararg| {
|
||||
vm.to_repr(vararg)
|
||||
.unwrap_or_else(|_| PyStr::from("<element repr() failed>").into_ref(vm))
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ExceptionCtor {
|
||||
Class(PyTypeRef),
|
||||
@@ -244,20 +270,10 @@ impl TryFromObject for ExceptionCtor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invoke(
|
||||
cls: PyTypeRef,
|
||||
args: Vec<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyBaseExceptionRef> {
|
||||
// TODO: fast-path built-in exceptions by directly instantiating them? Is that really worth it?
|
||||
let res = vm.invoke(cls.as_object(), args)?;
|
||||
res.try_into_value(vm)
|
||||
}
|
||||
|
||||
impl ExceptionCtor {
|
||||
pub fn instantiate(self, vm: &VirtualMachine) -> PyResult<PyBaseExceptionRef> {
|
||||
match self {
|
||||
Self::Class(cls) => invoke(cls, vec![], vm),
|
||||
Self::Class(cls) => vm.invoke_exception(cls, vec![]),
|
||||
Self::Instance(exc) => Ok(exc),
|
||||
}
|
||||
}
|
||||
@@ -286,35 +302,12 @@ impl ExceptionCtor {
|
||||
exc @ PyBaseException => exc.args().as_slice().to_vec(),
|
||||
obj => vec![obj],
|
||||
});
|
||||
invoke(cls, args, vm)
|
||||
vm.invoke_exception(cls, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split(
|
||||
exc: PyBaseExceptionRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyObjectRef, PyObjectRef, PyObjectRef) {
|
||||
let tb = exc.traceback().into_pyobject(vm);
|
||||
(exc.clone_class().into(), exc.into(), tb)
|
||||
}
|
||||
|
||||
/// Similar to PyErr_NormalizeException in CPython
|
||||
pub fn normalize(
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: PyObjectRef,
|
||||
exc_tb: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyBaseExceptionRef> {
|
||||
let ctor = ExceptionCtor::try_from_object(vm, exc_type)?;
|
||||
let exc = ctor.instantiate_value(exc_val, vm)?;
|
||||
if let Some(tb) = Option::<PyTracebackRef>::try_from_object(vm, exc_tb)? {
|
||||
exc.set_traceback(Some(tb));
|
||||
}
|
||||
Ok(exc)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExceptionZoo {
|
||||
pub base_exception_type: PyTypeRef,
|
||||
@@ -497,7 +490,7 @@ impl PyBaseException {
|
||||
|
||||
#[pymethod(magic)]
|
||||
pub(super) fn str(&self, vm: &VirtualMachine) -> PyStrRef {
|
||||
let str_args = exception_args_as_string(vm, self.args(), true);
|
||||
let str_args = vm.exception_args_as_string(self.args(), true);
|
||||
match str_args.into_iter().exactly_one() {
|
||||
Err(i) if i.len() == 0 => PyStr::from("").into_ref(vm),
|
||||
Ok(s) => s,
|
||||
@@ -507,7 +500,7 @@ impl PyBaseException {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
|
||||
let repr_args = exception_args_as_string(vm, zelf.args(), false);
|
||||
let repr_args = vm.exception_args_as_string(zelf.args(), false);
|
||||
let cls = zelf.class();
|
||||
format!("{}({})", cls.name(), repr_args.iter().format(", "))
|
||||
}
|
||||
@@ -843,7 +836,7 @@ fn make_arg_getter(idx: usize) -> impl Fn(PyBaseExceptionRef) -> Option<PyObject
|
||||
fn key_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyStrRef {
|
||||
let args = exc.args();
|
||||
if args.as_slice().len() == 1 {
|
||||
exception_args_as_string(vm, args, false)
|
||||
vm.exception_args_as_string(args, false)
|
||||
.into_iter()
|
||||
.exactly_one()
|
||||
.unwrap()
|
||||
@@ -923,7 +916,9 @@ impl serde::Serialize for SerializeException<'_> {
|
||||
|
||||
let rendered = {
|
||||
let mut rendered = String::new();
|
||||
write_exception(&mut rendered, self.vm, self.exc).map_err(S::Error::custom)?;
|
||||
self.vm
|
||||
.write_exception(&mut rendered, self.exc)
|
||||
.map_err(S::Error::custom)?;
|
||||
rendered
|
||||
};
|
||||
struc.serialize_field("rendered", &rendered)?;
|
||||
@@ -953,7 +948,6 @@ pub(super) mod types {
|
||||
use crate::common::lock::PyRwLock;
|
||||
use crate::{
|
||||
builtins::{traceback::PyTracebackRef, PyInt, PyTupleRef, PyTypeRef},
|
||||
exceptions::invoke,
|
||||
function::{FuncArgs, IntoPyResult},
|
||||
PyObjectRef, PyRef, PyResult, VirtualMachine,
|
||||
};
|
||||
@@ -1192,7 +1186,7 @@ pub(super) mod types {
|
||||
};
|
||||
|
||||
if error.is_some() {
|
||||
Some(invoke(error?, args.to_vec(), vm))
|
||||
Some(vm.invoke_exception(error?, args.to_vec()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
},
|
||||
bytecode,
|
||||
coroutine::Coro,
|
||||
exceptions::{self, ExceptionCtor},
|
||||
exceptions::ExceptionCtor,
|
||||
function::{FuncArgs, IntoPyResult},
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
scope::Scope,
|
||||
@@ -412,13 +412,13 @@ impl ExecutingFrame<'_> {
|
||||
self.push_value(val);
|
||||
self.run(vm)
|
||||
} else {
|
||||
let (ty, val, tb) = exceptions::split(err, vm);
|
||||
let (ty, val, tb) = vm.split_exception(err);
|
||||
self.gen_throw(vm, ty, val, tb)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
let exception = exceptions::normalize(exc_type, exc_val, exc_tb, vm)?;
|
||||
let exception = vm.normalize_exception(exc_type, exc_val, exc_tb)?;
|
||||
match self.unwind_blocks(vm, UnwindReason::Raising { exception }) {
|
||||
Ok(None) => self.run(vm),
|
||||
Ok(Some(result)) => Ok(result),
|
||||
@@ -801,7 +801,7 @@ impl ExecutingFrame<'_> {
|
||||
let exit = self.pop_value();
|
||||
|
||||
let args = if let Some(exc) = exc {
|
||||
exceptions::split(exc, vm)
|
||||
vm.split_exception(exc)
|
||||
} else {
|
||||
(vm.ctx.none(), vm.ctx.none(), vm.ctx.none())
|
||||
};
|
||||
|
||||
@@ -81,7 +81,6 @@ mod _io {
|
||||
PyBaseExceptionRef, PyByteArray, PyBytes, PyBytesRef, PyIntRef, PyMemoryView, PyStr,
|
||||
PyStrRef, PyType, PyTypeRef,
|
||||
},
|
||||
exceptions,
|
||||
function::{
|
||||
ArgBytesLike, ArgIterable, ArgMemoryBuffer, FuncArgs, IntoPyObject, OptionalArg,
|
||||
OptionalOption,
|
||||
@@ -1539,7 +1538,7 @@ mod _io {
|
||||
}
|
||||
let flush_res = data.flush(vm);
|
||||
let close_res = vm.call_method(data.raw.as_ref().unwrap(), "close", ());
|
||||
exceptions::chain(flush_res, close_res)
|
||||
exeption_chain(flush_res, close_res)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -1555,7 +1554,7 @@ mod _io {
|
||||
let data = zelf.lock(vm)?;
|
||||
let raw = data.raw.as_ref().unwrap();
|
||||
let close_res = vm.call_method(raw, "close", ());
|
||||
exceptions::chain(flush_res, close_res)
|
||||
exeption_chain(flush_res, close_res)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -1644,6 +1643,17 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
fn exeption_chain<T>(e1: PyResult<()>, e2: PyResult<T>) -> PyResult<T> {
|
||||
match (e1, e2) {
|
||||
(Err(e1), Err(e)) => {
|
||||
e.set_context(Some(e1));
|
||||
Err(e)
|
||||
}
|
||||
(Err(e), Ok(_)) | (Ok(()), Err(e)) => Err(e),
|
||||
(Ok(()), Ok(close_res)) => Ok(close_res),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "BufferedReader", base = "_BufferedIOBase")]
|
||||
#[derive(Debug, Default, PyValue)]
|
||||
@@ -1831,7 +1841,7 @@ mod _io {
|
||||
fn close(&self, vm: &VirtualMachine) -> PyResult {
|
||||
let write_res = self.write.close_strict(vm).map(drop);
|
||||
let read_res = self.read.close_strict(vm);
|
||||
exceptions::chain(write_res, read_res)
|
||||
exeption_chain(write_res, read_res)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2855,7 +2865,7 @@ mod _io {
|
||||
}
|
||||
let flush_res = vm.call_method(zelf.as_object(), "flush", ()).map(drop);
|
||||
let close_res = vm.call_method(&buffer, "close", ()).map(drop);
|
||||
exceptions::chain(flush_res, close_res)
|
||||
exeption_chain(flush_res, close_res)
|
||||
}
|
||||
#[pyproperty]
|
||||
fn closed(&self, vm: &VirtualMachine) -> PyResult {
|
||||
|
||||
@@ -12,7 +12,6 @@ mod sys {
|
||||
};
|
||||
use crate::{
|
||||
builtins::{PyDictRef, PyListRef, PyNamespace, PyStr, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
exceptions,
|
||||
frame::FrameRef,
|
||||
function::{FuncArgs, OptionalArg, PosArgs},
|
||||
stdlib::builtins,
|
||||
@@ -308,15 +307,15 @@ mod sys {
|
||||
exc_tb: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let exc = exceptions::normalize(exc_type, exc_val, exc_tb, vm)?;
|
||||
let exc = vm.normalize_exception(exc_type, exc_val, exc_tb)?;
|
||||
let stderr = super::get_stderr(vm)?;
|
||||
exceptions::write_exception(&mut crate::py_io::PyWriter(stderr, vm), vm, &exc)
|
||||
vm.write_exception(&mut crate::py_io::PyWriter(stderr, vm), &exc)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn exc_info(vm: &VirtualMachine) -> (PyObjectRef, PyObjectRef, PyObjectRef) {
|
||||
match vm.topmost_exception() {
|
||||
Some(exception) => exceptions::split(exception, vm),
|
||||
Some(exception) => vm.split_exception(exception),
|
||||
None => (vm.ctx.none(), vm.ctx.none(), vm.ctx.none()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ pub(crate) use _thread::{make_module, RawRMutex};
|
||||
pub(crate) mod _thread {
|
||||
use crate::{
|
||||
builtins::{PyDictRef, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
exceptions,
|
||||
function::{ArgCallable, FuncArgs, IntoPyException, KwArgs, OptionalArg},
|
||||
py_io,
|
||||
slots::{SlotConstructor, SlotGetattro, SlotSetattro},
|
||||
@@ -266,7 +265,7 @@ pub(crate) mod _thread {
|
||||
.as_ref()
|
||||
.map_or("<object repr() failed>", |s| s.as_str());
|
||||
writeln!(*stderr, "Exception ignored in thread started by: {}", repr)
|
||||
.and_then(|()| exceptions::write_exception(&mut stderr, vm, &exc))
|
||||
.and_then(|()| vm.write_exception(&mut stderr, &exc))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::{
|
||||
bytecode,
|
||||
codecs::CodecsRegistry,
|
||||
common::{ascii, hash::HashSecret, lock::PyMutex, rc::PyRc},
|
||||
exceptions,
|
||||
frame::{ExecutionResult, Frame, FrameRef},
|
||||
frozen,
|
||||
function::{FuncArgs, IntoFuncArgs, IntoPyObject},
|
||||
@@ -478,7 +477,7 @@ impl VirtualMachine {
|
||||
stdlib::sys::PyStderr(self),
|
||||
"Error in atexit._run_exitfuncs:"
|
||||
);
|
||||
exceptions::print_exception(self, e);
|
||||
self.print_exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -819,7 +818,7 @@ impl VirtualMachine {
|
||||
{
|
||||
let show_backtrace = std::env::var_os("RUST_BACKTRACE").map_or(false, |v| &v != "0");
|
||||
let after = if show_backtrace {
|
||||
exceptions::print_exception(self, exc);
|
||||
self.print_exception(exc);
|
||||
"exception backtrace above"
|
||||
} else {
|
||||
"run with RUST_BACKTRACE=1 to see Python backtrace"
|
||||
@@ -835,7 +834,7 @@ impl VirtualMachine {
|
||||
fn error(s: &str);
|
||||
}
|
||||
let mut s = String::new();
|
||||
exceptions::write_exception(&mut s, self, &exc).unwrap();
|
||||
self.write_exception(&mut s, &exc).unwrap();
|
||||
error(&s);
|
||||
panic!("{}; exception backtrace above", msg)
|
||||
}
|
||||
|
||||
@@ -575,11 +575,10 @@ impl AwaitPromise {
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
let err = rustpython_vm::exceptions::normalize(
|
||||
let err = vm.normalize_exception(
|
||||
exc_type,
|
||||
exc_val.unwrap_or_none(vm),
|
||||
exc_tb.unwrap_or_none(vm),
|
||||
vm,
|
||||
)?;
|
||||
Err(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user