Skip to content

Commit b5785e2

Browse files
authored
Use _print_exception_bltin in excepthook, register source in linecache (#7177)
- excepthook: call traceback._print_exception_bltin instead of traceback.print_exception to match PyErr_Display behavior - run_string: register compiled code in linecache._interactive_cache so traceback can display source lines and caret indicators - Remove test_sys_tracebacklimit expectedFailure
1 parent ccccaaf commit b5785e2

File tree

5 files changed

+22
-7
lines changed

5 files changed

+22
-7
lines changed

.cspell.dict/cpython.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ badsyntax
1111
baseinfo
1212
basetype
1313
binop
14+
bltin
1415
boolop
1516
BUFMAX
1617
BUILDSTDLIB

Lib/test/test_sys.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,6 @@ def test_getandroidapilevel(self):
12321232
self.assertIsInstance(level, int)
12331233
self.assertGreater(level, 0)
12341234

1235-
@unittest.expectedFailure # TODO: RUSTPYTHON
12361235
@force_not_colorized
12371236
@support.requires_subprocess()
12381237
def test_sys_tracebacklimit(self):

Lib/test/test_warnings/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,6 @@ def test_envvar_and_command_line(self):
14781478
self.assertEqual(stdout,
14791479
b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']")
14801480

1481-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: b"['error::DeprecationWarning']" != b"['default::DeprecationWarning', 'error::DeprecationWarning']"
14821481
@force_not_colorized
14831482
def test_conflicting_envvar_and_command_line(self):
14841483
rc, stdout, stderr = assert_python_failure("-Werror::DeprecationWarning", "-c",

crates/vm/src/stdlib/sys.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -825,11 +825,13 @@ mod sys {
825825
let stderr = super::get_stderr(vm)?;
826826
match vm.normalize_exception(exc_type.clone(), exc_val.clone(), exc_tb) {
827827
Ok(exc) => {
828-
// Try Python traceback module first for richer output
829-
// (enables features like keyword typo suggestions in SyntaxError)
828+
// PyErr_Display: try traceback._print_exception_bltin first
830829
if let Ok(tb_mod) = vm.import("traceback", 0)
831-
&& let Ok(print_exc) = tb_mod.get_attr("print_exception", vm)
832-
&& print_exc.call((exc.as_object().to_owned(),), vm).is_ok()
830+
&& let Ok(print_exc_builtin) =
831+
tb_mod.get_attr("_print_exception_bltin", vm)
832+
&& print_exc_builtin
833+
.call((exc.as_object().to_owned(),), vm)
834+
.is_ok()
833835
{
834836
return Ok(());
835837
}

crates/vm/src/vm/python_run.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Python code execution functions.
22
33
use crate::{
4-
PyResult, VirtualMachine,
4+
AsObject, PyRef, PyResult, VirtualMachine,
5+
builtins::PyCode,
56
compiler::{self},
67
scope::Scope,
78
};
@@ -22,9 +23,22 @@ impl VirtualMachine {
2223
let code_obj = self
2324
.compile(source, compiler::Mode::Exec, source_path)
2425
.map_err(|err| self.new_syntax_error(&err, Some(source)))?;
26+
// linecache._register_code(code, source, filename)
27+
let _ = self.register_code_in_linecache(&code_obj, source);
2528
self.run_code_obj(code_obj, scope)
2629
}
2730

31+
/// Register a code object's source in linecache._interactive_cache
32+
/// so that traceback can display source lines and caret indicators.
33+
fn register_code_in_linecache(&self, code: &PyRef<PyCode>, source: &str) -> PyResult<()> {
34+
let linecache = self.import("linecache", 0)?;
35+
let register = linecache.get_attr("_register_code", self)?;
36+
let source_str = self.ctx.new_str(source);
37+
let filename = self.ctx.new_str(code.source_path().as_str());
38+
register.call((code.as_object().to_owned(), source_str, filename), self)?;
39+
Ok(())
40+
}
41+
2842
#[deprecated(note = "use run_string instead")]
2943
pub fn run_code_string(&self, scope: Scope, source: &str, source_path: String) -> PyResult {
3044
self.run_string(scope, source, source_path)

0 commit comments

Comments
 (0)