Skip to content

Commit 9f714e8

Browse files
committed
Change remove_importlib_frames to work with tb object
1 parent c0bade2 commit 9f714e8

File tree

3 files changed

+55
-45
lines changed

3 files changed

+55
-45
lines changed

vm/src/frame.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::obj::objlist;
1414
use crate::obj::objslice::PySlice;
1515
use crate::obj::objstr;
1616
use crate::obj::objstr::PyString;
17-
use crate::obj::objtraceback::PyTraceback;
17+
use crate::obj::objtraceback::{PyTraceback, PyTracebackRef};
1818
use crate::obj::objtuple::PyTuple;
1919
use crate::obj::objtype;
2020
use crate::obj::objtype::PyClassRef;
@@ -191,12 +191,21 @@ impl Frame {
191191
let traceback = vm
192192
.get_attribute(exception.clone(), "__traceback__")
193193
.unwrap();
194+
195+
let next = if vm.is_none(&traceback) {
196+
None
197+
} else {
198+
let traceback: PyTracebackRef = traceback
199+
.downcast()
200+
.expect("next must be a traceback object");
201+
Some(traceback)
202+
};
203+
194204
let new_traceback = PyTraceback::new(
195-
traceback,
205+
next,
196206
self.clone().into_ref(vm),
197207
self.lasti.get(),
198208
lineno.row(),
199-
vm,
200209
);
201210
vm.set_attr(&exception, "__traceback__", new_traceback.into_ref(vm))
202211
.unwrap();

vm/src/import.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
use rand::Rng;
55

66
use crate::bytecode::CodeObject;
7-
use crate::obj::{objcode, objsequence, objstr, objtype};
7+
use crate::obj::objtraceback::{PyTraceback, PyTracebackRef};
8+
use crate::obj::{objcode, objtype};
89
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue};
910
use crate::scope::Scope;
1011
use crate::version::get_git_revision;
@@ -100,36 +101,50 @@ pub fn import_codeobj(
100101
Ok(module)
101102
}
102103

104+
fn remove_importlib_frames_inner(
105+
vm: &VirtualMachine,
106+
tb: Option<PyTracebackRef>,
107+
always_trim: bool,
108+
) -> Option<PyTracebackRef> {
109+
if tb.is_none() {
110+
return None;
111+
}
112+
let traceback = tb.unwrap();
113+
let file_name = traceback.frame.code.source_path.to_string();
114+
if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external" {
115+
if always_trim || traceback.frame.code.obj_name == "_call_with_frames_removed" {
116+
return remove_importlib_frames_inner(
117+
vm,
118+
traceback.next.as_ref().map(|x| x.clone()),
119+
always_trim,
120+
);
121+
}
122+
}
123+
124+
Some(
125+
PyTraceback::new(
126+
remove_importlib_frames_inner(
127+
vm,
128+
traceback.next.as_ref().map(|x| x.clone()),
129+
always_trim,
130+
),
131+
traceback.frame.clone(),
132+
traceback.lasti,
133+
traceback.lineno,
134+
)
135+
.into_ref(vm),
136+
)
137+
}
138+
103139
// TODO: This function should do nothing on verbose mode.
104140
pub fn remove_importlib_frames(vm: &VirtualMachine, exc: &PyObjectRef) -> PyObjectRef {
105141
let always_trim = objtype::isinstance(exc, &vm.ctx.exceptions.import_error);
106142

107143
if let Ok(tb) = vm.get_attribute(exc.clone(), "__traceback__") {
108-
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
109-
let tb_entries = objsequence::get_elements_list(&tb).to_vec();
110-
let mut in_importlib = false;
111-
let new_tb = tb_entries
112-
.iter()
113-
.filter(|tb_entry| {
114-
let location_attrs = objsequence::get_elements_tuple(&tb_entry);
115-
let file_name = objstr::get_value(&location_attrs[0]);
116-
if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external"
117-
{
118-
let run_obj_name = objstr::get_value(&location_attrs[2]);
119-
if run_obj_name == "_call_with_frames_removed" {
120-
in_importlib = true;
121-
}
122-
!always_trim && !in_importlib
123-
} else {
124-
in_importlib = false;
125-
true
126-
}
127-
})
128-
.cloned()
129-
.collect();
130-
vm.set_attr(exc, "__traceback__", vm.ctx.new_list(new_tb))
131-
.unwrap();
132-
}
144+
let base_tb: PyTracebackRef = tb.downcast().expect("must be a traceback object");
145+
let trimed_tb = remove_importlib_frames_inner(vm, Some(base_tb), always_trim)
146+
.map_or(vm.get_none(), |x| x.into_object());
147+
vm.set_attr(exc, "__traceback__", trimed_tb).unwrap();
133148
}
134149
exc.clone()
135150
}

vm/src/obj/objtraceback.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::frame::FrameRef;
22
use crate::obj::objtype::PyClassRef;
3-
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyValue};
3+
use crate::pyobject::{PyClassImpl, PyContext, PyRef, PyValue};
44
use crate::vm::VirtualMachine;
55

66
#[pyclass]
@@ -22,21 +22,7 @@ impl PyValue for PyTraceback {
2222

2323
#[pyimpl]
2424
impl PyTraceback {
25-
pub fn new(
26-
next: PyObjectRef,
27-
frame: FrameRef,
28-
lasti: usize,
29-
lineno: usize,
30-
vm: &VirtualMachine,
31-
) -> Self {
32-
let next = if vm.is_none(&next) {
33-
None
34-
} else {
35-
let traceback: PyTracebackRef =
36-
next.downcast().expect("next must be a traceback object");
37-
Some(traceback)
38-
};
39-
25+
pub fn new(next: Option<PyTracebackRef>, frame: FrameRef, lasti: usize, lineno: usize) -> Self {
4026
PyTraceback {
4127
next,
4228
frame,

0 commit comments

Comments
 (0)