|
4 | 4 | use rand::Rng;
|
5 | 5 |
|
6 | 6 | 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}; |
8 | 9 | use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue};
|
9 | 10 | use crate::scope::Scope;
|
10 | 11 | use crate::version::get_git_revision;
|
@@ -100,36 +101,50 @@ pub fn import_codeobj(
|
100 | 101 | Ok(module)
|
101 | 102 | }
|
102 | 103 |
|
| 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 | + |
103 | 139 | // TODO: This function should do nothing on verbose mode.
|
104 | 140 | pub fn remove_importlib_frames(vm: &VirtualMachine, exc: &PyObjectRef) -> PyObjectRef {
|
105 | 141 | let always_trim = objtype::isinstance(exc, &vm.ctx.exceptions.import_error);
|
106 | 142 |
|
107 | 143 | 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(); |
133 | 148 | }
|
134 | 149 | exc.clone()
|
135 | 150 | }
|
0 commit comments