Preserve panic message after exception is normalized

This commit is contained in:
David Hewitt 2023-07-11 08:36:44 +01:00
parent 421e13a89c
commit 2e2dde910a
2 changed files with 23 additions and 2 deletions

View File

@ -0,0 +1 @@
Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized".

View File

@ -297,9 +297,10 @@ impl PyErr {
}; };
if ptype.as_ptr() == PanicException::type_object_raw(py).cast() { if ptype.as_ptr() == PanicException::type_object_raw(py).cast() {
let msg: String = pvalue let msg = pvalue
.as_ref() .as_ref()
.and_then(|obj| obj.extract(py).ok()) .and_then(|obj| obj.as_ref(py).str().ok())
.map(|py_str| py_str.to_string_lossy().into())
.unwrap_or_else(|| String::from("Unwrapped panic from Python code")); .unwrap_or_else(|| String::from("Unwrapped panic from Python code"));
eprintln!( eprintln!(
@ -845,6 +846,25 @@ mod tests {
}); });
} }
#[test]
#[should_panic(expected = "new panic")]
#[cfg(not(Py_3_12))]
fn fetching_normalized_panic_exception_resumes_unwind() {
use crate::panic::PanicException;
Python::with_gil(|py| {
let err: PyErr = PanicException::new_err("new panic");
// Restoring an error doesn't normalize it before Python 3.12,
// so we have to explicitly test this case.
let _ = err.normalized(py);
err.restore(py);
assert!(PyErr::occurred(py));
// should resume unwind
let _ = PyErr::fetch(py);
});
}
#[test] #[test]
fn err_debug() { fn err_debug() {
// Debug representation should be like the following (without the newlines): // Debug representation should be like the following (without the newlines):