(&mut self, vm: &VirtualMachine, idx: bytecode::NameIdx)
| 6165 | |
| 6166 | #[cfg_attr(feature = "flame-it", flame("Frame"))] |
| 6167 | fn import_from(&mut self, vm: &VirtualMachine, idx: bytecode::NameIdx) -> PyResult { |
| 6168 | let module = self.top_value(); |
| 6169 | let name = self.code.names[idx as usize]; |
| 6170 | |
| 6171 | // Load attribute, and transform any error into import error. |
| 6172 | if let Some(obj) = vm.get_attribute_opt(module.to_owned(), name)? { |
| 6173 | return Ok(obj); |
| 6174 | } |
| 6175 | // fallback to importing '{module.__name__}.{name}' from sys.modules |
| 6176 | let fallback_module = (|| { |
| 6177 | let mod_name = module.get_attr(identifier!(vm, __name__), vm).ok()?; |
| 6178 | let mod_name = mod_name.downcast_ref::<PyStr>()?; |
| 6179 | let full_mod_name = format!("{mod_name}.{name}"); |
| 6180 | let sys_modules = vm.sys_module.get_attr("modules", vm).ok()?; |
| 6181 | sys_modules.get_item(&full_mod_name, vm).ok() |
| 6182 | })(); |
| 6183 | |
| 6184 | if let Some(sub_module) = fallback_module { |
| 6185 | return Ok(sub_module); |
| 6186 | } |
| 6187 | |
| 6188 | use crate::import::{ |
| 6189 | get_spec_file_origin, is_possibly_shadowing_path, is_stdlib_module_name, |
| 6190 | }; |
| 6191 | |
| 6192 | // Get module name for the error message |
| 6193 | let mod_name_obj = module.get_attr(identifier!(vm, __name__), vm).ok(); |
| 6194 | let mod_name_str = mod_name_obj |
| 6195 | .as_ref() |
| 6196 | .and_then(|n| n.downcast_ref::<PyUtf8Str>().map(|s| s.as_str().to_owned())); |
| 6197 | let module_name = mod_name_str.as_deref().unwrap_or("<unknown module name>"); |
| 6198 | |
| 6199 | let spec = module |
| 6200 | .get_attr("__spec__", vm) |
| 6201 | .ok() |
| 6202 | .filter(|s| !vm.is_none(s)); |
| 6203 | |
| 6204 | let origin = get_spec_file_origin(&spec, vm); |
| 6205 | |
| 6206 | let is_possibly_shadowing = origin |
| 6207 | .as_ref() |
| 6208 | .map(|o| is_possibly_shadowing_path(o, vm)) |
| 6209 | .unwrap_or(false); |
| 6210 | let is_possibly_shadowing_stdlib = if is_possibly_shadowing { |
| 6211 | if let Some(ref mod_name) = mod_name_obj { |
| 6212 | is_stdlib_module_name(mod_name, vm)? |
| 6213 | } else { |
| 6214 | false |
| 6215 | } |
| 6216 | } else { |
| 6217 | false |
| 6218 | }; |
| 6219 | |
| 6220 | let msg = if is_possibly_shadowing_stdlib { |
| 6221 | let origin = origin.as_ref().unwrap(); |
| 6222 | format!( |
| 6223 | "cannot import name '{name}' from '{module_name}' \ |
| 6224 | (consider renaming '{origin}' since it has the same \ |
no test coverage detected