allow `from` imports in nonglobal scopes to add available submodule attributes

This commit is contained in:
Alex Waygood 2025-11-23 22:51:34 +00:00 committed by Aria Desires
parent b60910c82b
commit 73af08a520
2 changed files with 42 additions and 1 deletions

View File

@ -116,3 +116,43 @@ b = 1
```py
```
## Submodule is loaded in a non-global scope
We recognise submodules as being available as attributes even if they are loaded in a function
scope. The function might never be executed, which means that the submodule might never be loaded;
however, we prefer to prioritise avoiding false positives over catching all possible errors here.
`a/b.py`:
```py
```
`a/c.py`:
```py
d = 42
```
`a/e/f.py`:
```py
```
`main.py`:
```py
import a
def f():
import a.b
from a.c import d
from a.e import f
f()
reveal_type(a.b) # revealed: <module 'a.b'>
reveal_type(a.c) # revealed: <module 'a.c'>
reveal_type(a.e) # revealed: <module 'a.e'>
reveal_type(a.e.f) # revealed: <module 'a.e.f'>
```

View File

@ -1531,11 +1531,12 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
is_self_import = &module_name == thispackage;
}
if self.current_scope().is_global() && node.module.is_some() {
if node.module.is_some() {
if let Ok(thispackage) = this_package
&& let Some(relative_submodule) = module_name.relative_to(&thispackage)
{
if is_package
&& self.current_scope().is_global()
&& let Some(direct_submodule) =
relative_submodule.components().next()
&& !self.seen_submodule_imports.contains(direct_submodule)