From a3afe9dac1f8de8807a96466b0ca981e4773250b Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 11 Jul 2023 08:36:44 +0100 Subject: [PATCH] Preserve panic message after exception is normalized --- newsfragments/3326.fixed.md | 1 + src/err/mod.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 newsfragments/3326.fixed.md diff --git a/newsfragments/3326.fixed.md b/newsfragments/3326.fixed.md new file mode 100644 index 00000000000..8353c598f72 --- /dev/null +++ b/newsfragments/3326.fixed.md @@ -0,0 +1 @@ +Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". diff --git a/src/err/mod.rs b/src/err/mod.rs index cdfb64b1249..1daedec2820 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -299,7 +299,7 @@ impl PyErr { if ptype.as_ptr() == PanicException::type_object_raw(py).cast() { let msg: String = pvalue .as_ref() - .and_then(|obj| obj.extract(py).ok()) + .map(|obj| obj.as_ref(py).to_string()) .unwrap_or_else(|| String::from("Unwrapped panic from Python code")); eprintln!( @@ -845,6 +845,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] fn err_debug() { // Debug representation should be like the following (without the newlines):