-
Notifications
You must be signed in to change notification settings - Fork 678
/
traceback.rs
82 lines (75 loc) · 2.4 KB
/
traceback.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::err::{error_on_minusone, PyResult};
use crate::ffi;
use crate::types::PyString;
use crate::{AsPyPointer, PyAny};
/// Represents a Python traceback.
#[repr(transparent)]
pub struct PyTraceback(PyAny);
pyobject_native_type_core!(
PyTraceback,
ffi::PyTraceBack_Type,
#checkfunction=ffi::PyTraceBack_Check
);
impl PyTraceback {
/// Formats the traceback as a string.
///
/// This does not include the exception type and value. The exception type and value can be
/// formatted using the `Display` implementation for `PyErr`.
///
/// # Example
///
/// The following code formats a Python traceback and exception pair from Rust:
///
/// ```rust
/// # use pyo3::{Python, PyResult};
/// # let result: PyResult<()> =
/// Python::with_gil(|py| {
/// let err = py
/// .run("raise Exception('banana')", None, None)
/// .expect_err("raise will create a Python error");
///
/// let traceback = err.ptraceback(py).expect("raised exception will have a traceback");
/// assert_eq!(
/// format!("{}{}", traceback.format()?, err),
/// "\
/// Traceback (most recent call last):
/// File \"<string>\", line 1, in <module>
/// Exception: banana\
/// "
/// );
/// Ok(())
/// })
/// # ;
/// # result.expect("example failed");
/// ```
pub fn format(&self) -> PyResult<String> {
let py = self.py();
let string_io = py.import("io")?.getattr("StringIO")?.call0()?;
let result = unsafe { ffi::PyTraceBack_Print(self.as_ptr(), string_io.as_ptr()) };
error_on_minusone(py, result)?;
let formatted = string_io
.getattr("getvalue")?
.call0()?
.downcast::<PyString>()?
.to_str()?
.to_owned();
Ok(formatted)
}
}
#[cfg(test)]
mod tests {
use crate::Python;
#[test]
fn format_traceback() {
Python::with_gil(|py| {
let err = py
.run("raise Exception('banana')", None, None)
.expect_err("raising should have given us an error");
assert_eq!(
err.ptraceback(py).unwrap().format().unwrap(),
"Traceback (most recent call last):\n File \"<string>\", line 1, in <module>\n"
);
})
}
}