diff --git a/examples/freeze/main.rs b/examples/freeze/main.rs index 5de2844fc3..fec904a948 100644 --- a/examples/freeze/main.rs +++ b/examples/freeze/main.rs @@ -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(()) diff --git a/examples/mini_repl.rs b/examples/mini_repl.rs index b24fe7fc2c..87bf9b7c3e 100644 --- a/examples/mini_repl.rs +++ b/examples/mini_repl.rs @@ -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); } } } diff --git a/src/lib.rs b/src/lib.rs index 823377c93a..3655ffd6cc 100644 --- a/src/lib.rs +++ b/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 } }; diff --git a/src/shell.rs b/src/shell.rs index 4fb91b4994..f112f30844 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -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(); diff --git a/vm/src/coroutine.rs b/vm/src/coroutine.rs index 58c69e98ed..eedb4579d8 100644 --- a/vm/src/coroutine.rs +++ b/vm/src/coroutine.rs @@ -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 { 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); diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 0c627c2238..798c428010 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -31,48 +31,175 @@ impl PyValue for PyBaseException { } } -pub fn chain(e1: PyResult<()>, e2: PyResult) -> PyResult { - 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( - output: &mut W, - vm: &VirtualMachine, - exc: &PyBaseExceptionRef, -) -> Result<(), W::Error> { - let seen = &mut HashSet::::new(); - write_exception_recursive(output, vm, exc, seen) + pub fn write_exception( + &self, + output: &mut W, + exc: &PyBaseExceptionRef, + ) -> Result<(), W::Error> { + let seen = &mut HashSet::::new(); + self.write_exception_recursive(output, exc, seen) + } + + fn write_exception_recursive( + &self, + output: &mut W, + exc: &PyBaseExceptionRef, + seen: &mut HashSet, + ) -> 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( + &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 { + 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("").into_ref(vm)) + } else { + vm.to_repr(&varargs[0]) + .unwrap_or_else(|_| PyStr::from("").into_ref(vm)) + }; + vec![args0_repr] + } + _ => varargs + .iter() + .map(|vararg| { + vm.to_repr(vararg) + .unwrap_or_else(|_| PyStr::from("").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 { + let ctor = ExceptionCtor::try_from_object(self, exc_type)?; + let exc = ctor.instantiate_value(exc_val, self)?; + if let Some(tb) = Option::::try_from_object(self, exc_tb)? { + exc.set_traceback(Some(tb)); + } + Ok(exc) + } + + pub fn invoke_exception( + &self, + cls: PyTypeRef, + args: Vec, + ) -> PyResult { + // 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( @@ -117,107 +244,6 @@ fn write_traceback_entry( Ok(()) } -fn write_exception_recursive( - output: &mut W, - vm: &VirtualMachine, - exc: &PyBaseExceptionRef, - seen: &mut HashSet, -) -> 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( - 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 { - 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("").into_ref(vm)) - } else { - vm.to_repr(&varargs[0]) - .unwrap_or_else(|_| PyStr::from("").into_ref(vm)) - }; - vec![args0_repr] - } - _ => varargs - .iter() - .map(|vararg| { - vm.to_repr(vararg) - .unwrap_or_else(|_| PyStr::from("").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, - vm: &VirtualMachine, -) -> PyResult { - // 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 { 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 { - let ctor = ExceptionCtor::try_from_object(vm, exc_type)?; - let exc = ctor.instantiate_value(exc_val, vm)?; - if let Some(tb) = Option::::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, 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 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 } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 4548d37da8..12772ada8c 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -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()) }; diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 1700270762..5bce32ba3a 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -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(e1: PyResult<()>, e2: PyResult) -> PyResult { + 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 { diff --git a/vm/src/stdlib/sys.rs b/vm/src/stdlib/sys.rs index 9521805d41..a2e342ea7b 100644 --- a/vm/src/stdlib/sys.rs +++ b/vm/src/stdlib/sys.rs @@ -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()), } } diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index 24bf38c963..3888bb1528 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -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("", |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(); } } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 5d3a624ef4..13cd80c7f4 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -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) } diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index b9e6edf873..e4a5b9b77a 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -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) }