|
4 | 4 | // git clone https://github.com/marcomq/tauri-plugin-python
|
5 | 5 |
|
6 | 6 | #[cfg(feature = "pyo3")]
|
7 |
| -use pyo3::PyErr; |
| 7 | +use pyo3::{prelude::*, PyErr}; |
8 | 8 | use serde::{ser::Serializer, Serialize};
|
9 | 9 |
|
10 | 10 | pub type Result<T> = std::result::Result<T, Error>;
|
@@ -63,9 +63,95 @@ impl From<rustpython_vm::PyRef<rustpython_vm::builtins::PyBaseException>> for Er
|
63 | 63 | #[cfg(feature = "pyo3")]
|
64 | 64 | impl From<PyErr> for Error {
|
65 | 65 | fn from(error: PyErr) -> Self {
|
66 |
| - let msg = error.to_string(); |
67 |
| - println!("error: {}", &msg); |
68 |
| - Error::String(msg) |
| 66 | + let error_msg = match pyo3::Python::with_gil(|py| -> Result<Vec<String>> { |
| 67 | + let traceback_module = py.import("traceback")?; |
| 68 | + let traceback_object = error |
| 69 | + .traceback(py) |
| 70 | + .ok_or(pyo3::exceptions::PyWarning::new_err("No traceback found."))?; |
| 71 | + let extract_traceback = traceback_module.getattr("extract_tb")?; |
| 72 | + |
| 73 | + // Get the formatted traceback lines |
| 74 | + let result = extract_traceback.call1((traceback_object,)).and_then(|r| { |
| 75 | + match r.extract::<Vec<PyObject>>() { |
| 76 | + Ok(v) => { |
| 77 | + let mut formatted_lines = Vec::new(); |
| 78 | + for arg in v.iter() { |
| 79 | + let frame = arg.bind(py); |
| 80 | + |
| 81 | + // Extract filename |
| 82 | + let filename = match frame.getattr("filename") { |
| 83 | + Ok(f) => match f.extract::<String>() { |
| 84 | + Ok(s) if s == "<string>".to_string() => { |
| 85 | + // Special handling for <string> |
| 86 | + frame.setattr("filename", "main.py")?; |
| 87 | + let lineno = frame.getattr("lineno")?.extract::<usize>()?; |
| 88 | + frame.setattr("lineno", lineno - 2)?; |
| 89 | + "main.py".to_string() |
| 90 | + } |
| 91 | + Ok(s) => s, |
| 92 | + Err(_) => "<unknown>".to_string(), |
| 93 | + }, |
| 94 | + Err(_) => "<unknown>".to_string(), |
| 95 | + }; |
| 96 | + |
| 97 | + // Extract line number |
| 98 | + let lineno = match frame.getattr("lineno") { |
| 99 | + Ok(l) => match l.extract::<usize>() { |
| 100 | + Ok(n) => n, |
| 101 | + Err(_) => 0, |
| 102 | + }, |
| 103 | + Err(_) => 0, |
| 104 | + }; |
| 105 | + |
| 106 | + // Extract function name |
| 107 | + let name = match frame.getattr("name") { |
| 108 | + Ok(n) => match n.extract::<String>() { |
| 109 | + Ok(s) => s, |
| 110 | + Err(_) => "<unknown>".to_string(), |
| 111 | + }, |
| 112 | + Err(_) => "<unknown>".to_string(), |
| 113 | + }; |
| 114 | + |
| 115 | + // Extract line content (if available) |
| 116 | + let line = match frame.getattr("line") { |
| 117 | + Ok(l) => match l.extract::<Option<String>>() { |
| 118 | + Ok(Some(s)) => format!("\t{}", s), |
| 119 | + _ => "".to_string(), |
| 120 | + }, |
| 121 | + Err(_) => "".to_string(), |
| 122 | + }; |
| 123 | + |
| 124 | + // Format the line like requested |
| 125 | + let formatted_line = format!( |
| 126 | + "File \"{}\", line {}, in {}\n{}", |
| 127 | + filename, lineno, name, line |
| 128 | + ); |
| 129 | + |
| 130 | + formatted_lines.push(formatted_line); |
| 131 | + } |
| 132 | + |
| 133 | + Ok(formatted_lines) |
| 134 | + } |
| 135 | + Err(_) => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
| 136 | + "Failed to extract traceback", |
| 137 | + )), |
| 138 | + } |
| 139 | + })?; |
| 140 | + |
| 141 | + // Add traceback header |
| 142 | + let mut full_traceback = vec!["Traceback (most recent call last):".to_string()]; |
| 143 | + full_traceback.extend(result); |
| 144 | + |
| 145 | + // Add error type and message |
| 146 | + full_traceback.push(error.to_string()); |
| 147 | + |
| 148 | + Ok(full_traceback) |
| 149 | + }) { |
| 150 | + Ok(formatted) => formatted.join("\n"), |
| 151 | + Err(_) => error.to_string(), // Fall back to simple error message |
| 152 | + }; |
| 153 | + |
| 154 | + Error::String(error_msg) |
69 | 155 | }
|
70 | 156 | }
|
71 | 157 |
|
|
0 commit comments