(spec: PyObjectRef, vm: &VirtualMachine)
| 198 | |
| 199 | #[pyfunction] |
| 200 | fn create_builtin(spec: PyObjectRef, vm: &VirtualMachine) -> PyResult { |
| 201 | let sys_modules = vm.sys_module.get_attr("modules", vm).unwrap(); |
| 202 | let name: PyUtf8StrRef = spec.get_attr("name", vm)?.try_into_value(vm)?; |
| 203 | |
| 204 | // Check sys.modules first |
| 205 | if let Ok(module) = sys_modules.get_item(&*name, vm) { |
| 206 | return Ok(module); |
| 207 | } |
| 208 | |
| 209 | let name_str = name.as_str(); |
| 210 | if let Some(&def) = vm.state.module_defs.get(name_str) { |
| 211 | // Phase 1: Create module (use create slot if provided, else default creation) |
| 212 | let module = if let Some(create) = def.slots.create { |
| 213 | // Custom module creation |
| 214 | create(vm, &spec, def)? |
| 215 | } else { |
| 216 | // Default module creation |
| 217 | PyModule::from_def(def).into_ref(&vm.ctx) |
| 218 | }; |
| 219 | |
| 220 | // Initialize module dict and methods |
| 221 | // Corresponds to PyModule_FromDefAndSpec: md_def, _add_methods_to_object, PyModule_SetDocString |
| 222 | PyModule::__init_dict_from_def(vm, &module); |
| 223 | module.__init_methods(vm)?; |
| 224 | |
| 225 | // Add to sys.modules BEFORE exec (critical for circular import handling) |
| 226 | sys_modules.set_item(name.as_pystr(), module.clone().into(), vm)?; |
| 227 | |
| 228 | // Phase 2: Call exec slot (can safely import other modules now) |
| 229 | if let Some(exec) = def.slots.exec { |
| 230 | exec(vm, &module)?; |
| 231 | } |
| 232 | |
| 233 | return Ok(module.into()); |
| 234 | } |
| 235 | |
| 236 | Ok(vm.ctx.none()) |
| 237 | } |
| 238 | |
| 239 | #[pyfunction] |
| 240 | fn exec_builtin(_mod: PyRef<PyModule>) -> i32 { |
nothing calls this directly
no test coverage detected