File: test_pyerr_debug_unformattable.rs

package info (click to toggle)
rust-pyo3 0.27.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,648 kB
  • sloc: javascript: 59; makefile: 58; python: 39; sh: 1
file content (66 lines) | stat: -rw-r--r-- 2,161 bytes parent folder | download
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
use pyo3::ffi;
use pyo3::prelude::*;

// This test mucks around with sys.modules, so run it separately to prevent it
// from potentially corrupting the state of the python interpreter used in other
// tests.

#[test]
fn err_debug_unformattable() {
    // Debug representation should be like the following (without the newlines):
    // PyErr {
    //     type: <class 'Exception'>,
    //     value: Exception('banana'),
    //     traceback: Some(\"<unformattable <traceback object at 0x...>>\")
    // }

    Python::attach(|py| {
        // PyTracebackMethods::format uses io.StringIO. Mock it out to trigger a
        // formatting failure:
        // TypeError: 'Mock' object cannot be cast as 'str'
        let err = py
            .run(
                ffi::c_str!(
                    r#"
import io, sys, unittest.mock
sys.modules['orig_io'] = sys.modules['io']
sys.modules['io'] = unittest.mock.Mock()
raise Exception('banana')"#
                ),
                None,
                None,
            )
            .expect_err("raising should have given us an error");

        let debug_str = format!("{err:?}");
        assert!(debug_str.starts_with("PyErr { "));
        assert!(debug_str.ends_with(" }"));

        // Strip "PyErr { " and " }". Split into 3 substrings to separate type,
        // value, and traceback while not splitting the string within traceback.
        let mut fields = debug_str["PyErr { ".len()..debug_str.len() - 2].splitn(3, ", ");

        assert_eq!(fields.next().unwrap(), "type: <class 'Exception'>");
        assert_eq!(fields.next().unwrap(), "value: Exception('banana')");

        let traceback = fields.next().unwrap();
        assert!(
            traceback.starts_with("traceback: Some(\"<unformattable <traceback object at 0x"),
            "assertion failed, actual traceback str: {traceback:?}"
        );
        assert!(fields.next().is_none());

        py.run(
            ffi::c_str!(
                r#"
import io, sys, unittest.mock
sys.modules['io'] = sys.modules['orig_io']
del sys.modules['orig_io']
"#
            ),
            None,
            None,
        )
        .unwrap();
    });
}