(&self, name: &Py<PyStr>, vm: &VirtualMachine)
| 147 | } |
| 148 | |
| 149 | fn getattr_inner(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult { |
| 150 | if let Some(attr) = self.as_object().generic_getattr_opt(name, None, vm)? { |
| 151 | return Ok(attr); |
| 152 | } |
| 153 | if let Ok(getattr) = self.dict().get_item(identifier!(vm, __getattr__), vm) { |
| 154 | return getattr.call((name.to_owned(),), vm); |
| 155 | } |
| 156 | let dict = self.dict(); |
| 157 | |
| 158 | // Get the raw __name__ object (may be a str subclass) |
| 159 | let mod_name_obj = dict |
| 160 | .get_item_opt(identifier!(vm, __name__), vm) |
| 161 | .ok() |
| 162 | .flatten(); |
| 163 | let mod_name_str = mod_name_obj.as_ref().and_then(|n| { |
| 164 | n.downcast_ref::<PyStr>() |
| 165 | .map(|s| s.to_string_lossy().into_owned()) |
| 166 | }); |
| 167 | |
| 168 | // If __name__ is not set or not a string, use a simpler error message |
| 169 | let mod_display = match mod_name_str.as_deref() { |
| 170 | Some(s) => s, |
| 171 | None => { |
| 172 | return Err(vm.new_attribute_error(format!("module has no attribute '{name}'"))); |
| 173 | } |
| 174 | }; |
| 175 | |
| 176 | let spec = dict |
| 177 | .get_item_opt(vm.ctx.intern_str("__spec__"), vm) |
| 178 | .ok() |
| 179 | .flatten() |
| 180 | .filter(|s| !vm.is_none(s)); |
| 181 | |
| 182 | let origin = get_spec_file_origin(&spec, vm); |
| 183 | |
| 184 | let is_possibly_shadowing = origin |
| 185 | .as_ref() |
| 186 | .map(|o| is_possibly_shadowing_path(o, vm)) |
| 187 | .unwrap_or(false); |
| 188 | // Use the ORIGINAL __name__ object for stdlib check (may raise TypeError |
| 189 | // if __name__ is an unhashable str subclass) |
| 190 | let is_possibly_shadowing_stdlib = if is_possibly_shadowing { |
| 191 | if let Some(ref mod_name) = mod_name_obj { |
| 192 | is_stdlib_module_name(mod_name, vm)? |
| 193 | } else { |
| 194 | false |
| 195 | } |
| 196 | } else { |
| 197 | false |
| 198 | }; |
| 199 | |
| 200 | if is_possibly_shadowing_stdlib { |
| 201 | let origin = origin.as_ref().unwrap(); |
| 202 | Err(vm.new_attribute_error(format!( |
| 203 | "module '{mod_display}' has no attribute '{name}' \ |
| 204 | (consider renaming '{origin}' since it has the same \ |
| 205 | name as the standard library module named '{mod_display}' \ |
| 206 | and prevents importing that standard library module)" |
no test coverage detected