(exc: &Py<PyBaseException>, vm: &VirtualMachine)
| 48 | } |
| 49 | |
| 50 | pub fn offer_suggestions(exc: &Py<PyBaseException>, vm: &VirtualMachine) -> Option<PyStrRef> { |
| 51 | if exc |
| 52 | .class() |
| 53 | .fast_issubclass(vm.ctx.exceptions.attribute_error) |
| 54 | { |
| 55 | let name = exc.as_object().get_attr("name", vm).ok()?; |
| 56 | if vm.is_none(&name) { |
| 57 | return None; |
| 58 | } |
| 59 | let obj = exc.as_object().get_attr("obj", vm).ok()?; |
| 60 | if vm.is_none(&obj) { |
| 61 | return None; |
| 62 | } |
| 63 | |
| 64 | calculate_suggestions(vm.dir(Some(obj)).ok()?.borrow_vec().iter(), &name) |
| 65 | } else if exc.class().fast_issubclass(vm.ctx.exceptions.name_error) { |
| 66 | let name = exc.as_object().get_attr("name", vm).ok()?; |
| 67 | if vm.is_none(&name) { |
| 68 | return None; |
| 69 | } |
| 70 | let tb = exc.__traceback__()?; |
| 71 | let tb = tb.iter().last().unwrap_or(tb); |
| 72 | |
| 73 | let varnames = tb.frame.code.clone().co_varnames(vm); |
| 74 | if let Some(suggestions) = calculate_suggestions(varnames.iter(), &name) { |
| 75 | return Some(suggestions); |
| 76 | }; |
| 77 | |
| 78 | let globals: Vec<_> = tb.frame.globals.as_object().try_to_value(vm).ok()?; |
| 79 | if let Some(suggestions) = calculate_suggestions(globals.iter(), &name) { |
| 80 | return Some(suggestions); |
| 81 | }; |
| 82 | |
| 83 | let builtins: Vec<_> = tb.frame.builtins.try_to_value(vm).ok()?; |
| 84 | calculate_suggestions(builtins.iter(), &name) |
| 85 | } else if exc.class().fast_issubclass(vm.ctx.exceptions.import_error) { |
| 86 | let mod_name = exc.as_object().get_attr("name", vm).ok()?; |
| 87 | let wrong_name = exc.as_object().get_attr("name_from", vm).ok()?; |
| 88 | let mod_name_str = mod_name.downcast_ref::<PyStr>()?; |
| 89 | |
| 90 | // Look up the module in sys.modules |
| 91 | let sys_modules = vm.sys_module.get_attr("modules", vm).ok()?; |
| 92 | let module = sys_modules.get_item(mod_name_str, vm).ok()?; |
| 93 | |
| 94 | calculate_suggestions(vm.dir(Some(module)).ok()?.borrow_vec().iter(), &wrong_name) |
| 95 | } else { |
| 96 | None |
| 97 | } |
| 98 | } |
no test coverage detected