Skip to content

Commit 6239fe0

Browse files
committed
Remove importlib frames from traceback
1 parent 22c0b08 commit 6239fe0

File tree

2 files changed

+61
-25
lines changed

2 files changed

+61
-25
lines changed

vm/src/import.rs

+34-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use crate::bytecode::CodeObject;
66
use crate::frame::Scope;
7-
use crate::obj::objcode;
8-
use crate::pyobject::{ItemProtocol, PyResult, PyValue};
7+
use crate::obj::{objcode, objsequence, objstr, objtype};
8+
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue};
99
use crate::vm::VirtualMachine;
1010
#[cfg(feature = "rustpython-compiler")]
1111
use rustpython_compiler::compile;
@@ -82,3 +82,35 @@ pub fn import_codeobj(
8282
)?;
8383
Ok(module)
8484
}
85+
86+
pub fn remove_importlib_frames(vm: &VirtualMachine, exc: &PyObjectRef) -> PyObjectRef {
87+
let always_trim = objtype::isinstance(exc, &vm.ctx.exceptions.import_error);
88+
89+
if let Ok(tb) = vm.get_attribute(exc.clone(), "__traceback__") {
90+
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
91+
let mut tb_entries = objsequence::get_elements_list(&tb).to_vec();
92+
tb_entries.reverse();
93+
let mut new_tb = Vec::with_capacity(tb_entries.len());
94+
95+
for tb_entry in tb_entries.iter() {
96+
let mut current_chunk = vec![];
97+
let location_attrs = objsequence::get_elements_tuple(&tb_entry);
98+
let file_name = objstr::get_value(&location_attrs[0]);
99+
if file_name != "_frozen_importlib" && file_name != "_frozen_importlib_external" {
100+
current_chunk.clear();
101+
new_tb.push(tb_entry.clone())
102+
} else {
103+
current_chunk.push(tb_entry.clone());
104+
let run_obj_name = objstr::get_value(&location_attrs[0]);
105+
if run_obj_name == "_call_with_frames_removed" || always_trim {
106+
new_tb.append(&mut current_chunk);
107+
}
108+
};
109+
}
110+
new_tb.reverse();
111+
vm.set_attr(exc, "__traceback__", vm.ctx.new_list(new_tb))
112+
.unwrap();
113+
}
114+
}
115+
exc.clone()
116+
}

vm/src/vm.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::bytecode;
1515
use crate::frame::{ExecutionResult, Frame, FrameRef, Scope};
1616
use crate::frozen;
1717
use crate::function::PyFuncArgs;
18+
use crate::import;
1819
use crate::obj::objbool;
1920
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
2021
use crate::obj::objcode::{PyCode, PyCodeRef};
@@ -305,30 +306,33 @@ impl VirtualMachine {
305306

306307
pub fn import(&self, module: &str, from_list: &PyObjectRef, level: usize) -> PyResult {
307308
let sys_modules = self.get_attribute(self.sys_module.clone(), "modules")?;
308-
sys_modules.get_item(module.to_string(), self).or_else(|_| {
309-
let import_func = self
310-
.get_attribute(self.builtins.clone(), "__import__")
311-
.map_err(|_| self.new_import_error("__import__ not found".to_string()))?;
312-
313-
let (locals, globals) = if let Some(frame) = self.current_frame() {
314-
(
315-
frame.scope.get_locals().into_object(),
316-
frame.scope.globals.clone().into_object(),
309+
sys_modules
310+
.get_item(module.to_string(), self)
311+
.or_else(|_| {
312+
let import_func = self
313+
.get_attribute(self.builtins.clone(), "__import__")
314+
.map_err(|_| self.new_import_error("__import__ not found".to_string()))?;
315+
316+
let (locals, globals) = if let Some(frame) = self.current_frame() {
317+
(
318+
frame.scope.get_locals().into_object(),
319+
frame.scope.globals.clone().into_object(),
320+
)
321+
} else {
322+
(self.get_none(), self.get_none())
323+
};
324+
self.invoke(
325+
import_func,
326+
vec![
327+
self.ctx.new_str(module.to_string()),
328+
globals,
329+
locals,
330+
from_list.clone(),
331+
self.ctx.new_int(level),
332+
],
317333
)
318-
} else {
319-
(self.get_none(), self.get_none())
320-
};
321-
self.invoke(
322-
import_func,
323-
vec![
324-
self.ctx.new_str(module.to_string()),
325-
globals,
326-
locals,
327-
from_list.clone(),
328-
self.ctx.new_int(level),
329-
],
330-
)
331-
})
334+
})
335+
.map_err(|exc| import::remove_importlib_frames(self, &exc))
332336
}
333337

334338
/// Determines if `obj` is an instance of `cls`, either directly, indirectly or virtually via

0 commit comments

Comments
 (0)