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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::bytecode::CodeObject;
use crate::frame::Scope;
use crate::obj::{objcode, objsequence, objstr, objtype};
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue};
use crate::vm::VirtualMachine;
#[cfg(feature = "rustpython-compiler")]
use rustpython_compiler::compile;
pub fn init_importlib(vm: &VirtualMachine, external: bool) -> PyResult {
let importlib = import_frozen(vm, "_frozen_importlib")?;
let impmod = import_builtin(vm, "_imp")?;
let install = vm.get_attribute(importlib.clone(), "_install")?;
vm.invoke(install, vec![vm.sys_module.clone(), impmod])?;
vm.import_func
.replace(vm.get_attribute(importlib.clone(), "__import__")?);
if external && cfg!(feature = "rustpython-compiler") {
let install_external =
vm.get_attribute(importlib.clone(), "_install_external_importers")?;
vm.invoke(install_external, vec![])?;
}
Ok(vm.get_none())
}
pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult {
vm.frozen
.borrow()
.get(module_name)
.ok_or_else(|| vm.new_import_error(format!("Cannot import frozen module {}", module_name)))
.and_then(|frozen| import_codeobj(vm, module_name, frozen.clone(), false))
}
pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {
vm.stdlib_inits
.borrow()
.get(module_name)
.ok_or_else(|| vm.new_import_error(format!("Cannot import bultin module {}", module_name)))
.and_then(|make_module_func| {
let module = make_module_func(vm);
let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules")?;
sys_modules.set_item(module_name, module.clone(), vm)?;
Ok(module)
})
}
#[cfg(feature = "rustpython-compiler")]
pub fn import_file(
vm: &VirtualMachine,
module_name: &str,
file_path: String,
content: String,
) -> PyResult {
let code_obj = compile::compile(&content, &compile::Mode::Exec, file_path)
.map_err(|err| vm.new_syntax_error(&err))?;
import_codeobj(vm, module_name, code_obj, true)
}
pub fn import_codeobj(
vm: &VirtualMachine,
module_name: &str,
code_obj: CodeObject,
set_file_attr: bool,
) -> PyResult {
let attrs = vm.ctx.new_dict();
attrs.set_item("__name__", vm.new_str(module_name.to_string()), vm)?;
if set_file_attr {
attrs.set_item("__file__", vm.new_str(code_obj.source_path.to_owned()), vm)?;
}
let module = vm.ctx.new_module(module_name, attrs.clone());
let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules")?;
sys_modules.set_item(module_name, module.clone(), vm)?;
vm.run_code_obj(
objcode::PyCode::new(code_obj).into_ref(vm),
Scope::with_builtins(None, attrs, vm),
)?;
Ok(module)
}
pub fn remove_importlib_frames(vm: &VirtualMachine, exc: &PyObjectRef) -> PyObjectRef {
let always_trim = objtype::isinstance(exc, &vm.ctx.exceptions.import_error);
if let Ok(tb) = vm.get_attribute(exc.clone(), "__traceback__") {
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
let tb_entries = objsequence::get_elements_list(&tb).to_vec();
let mut in_importlib = false;
let new_tb = tb_entries
.iter()
.filter(|tb_entry| {
let location_attrs = objsequence::get_elements_tuple(&tb_entry);
let file_name = objstr::get_value(&location_attrs[0]);
if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external"
{
let run_obj_name = objstr::get_value(&location_attrs[2]);
if run_obj_name == "_call_with_frames_removed" {
in_importlib = true;
}
!always_trim && !in_importlib
} else {
in_importlib = false;
true
}
})
.cloned()
.collect();
vm.set_attr(exc, "__traceback__", vm.ctx.new_list(new_tb))
.unwrap();
}
}
exc.clone()
}