(vm: &VirtualMachine, module_name: &str)
| 90 | } |
| 91 | |
| 92 | pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult { |
| 93 | let sys_modules = vm.sys_module.get_attr("modules", vm)?; |
| 94 | |
| 95 | // Check if already in sys.modules (handles recursive imports) |
| 96 | if let Ok(module) = sys_modules.get_item(module_name, vm) { |
| 97 | return Ok(module); |
| 98 | } |
| 99 | |
| 100 | // Try multi-phase init first (preferred for modules that import other modules) |
| 101 | if let Some(&def) = vm.state.module_defs.get(module_name) { |
| 102 | // Phase 1: Create and initialize module |
| 103 | let module = def.create_module(vm)?; |
| 104 | |
| 105 | // Add to sys.modules BEFORE exec (critical for circular import handling) |
| 106 | sys_modules.set_item(module_name, module.clone().into(), vm)?; |
| 107 | |
| 108 | // Phase 2: Call exec slot (can safely import other modules now) |
| 109 | // If exec fails, remove the partially-initialized module from sys.modules |
| 110 | if let Err(e) = def.exec_module(vm, &module) { |
| 111 | let _ = sys_modules.del_item(module_name, vm); |
| 112 | return Err(e); |
| 113 | } |
| 114 | |
| 115 | return Ok(module.into()); |
| 116 | } |
| 117 | |
| 118 | // Module not found in module_defs |
| 119 | Err(vm.new_import_error( |
| 120 | format!("Cannot import builtin module {module_name}"), |
| 121 | vm.ctx.new_utf8_str(module_name), |
| 122 | )) |
| 123 | } |
| 124 | |
| 125 | #[cfg(feature = "rustpython-compiler")] |
| 126 | pub fn import_file( |
no test coverage detected