Skip to content

Commit e87fee4

Browse files
authored
[red-knot] Add initial support for * imports (#16923)
## Summary This PR adds initial support for `*` imports to red-knot. The approach is to implement a standalone query, called from semantic indexing, that visits the module referenced by the `*` import and collects all global-scope public names that will be imported by the `*` import. The `SemanticIndexBuilder` then adds separate definitions for each of these names, all keyed to the same `ast::Alias` node that represents the `*` import. There are many pieces of `*`-import semantics that are still yet to be done, even with this PR: - This PR does not attempt to implement any of the semantics to do with `__all__`. (If a module defines `__all__`, then only the symbols included in `__all__` are imported, _not_ all public global-scope symbols. - With the logic implemented in this PR as it currently stands, we sometimes incorrectly consider a symbol bound even though it is defined in a branch that is statically known to be dead code, e.g. (assuming the target Python version is set to 3.11): ```py # a.py import sys if sys.version_info < (3, 10): class Foo: ... ``` ```py # b.py from a import * print(Foo) # this is unbound at runtime on 3.11, # but we currently consider it bound with the logic in this PR ``` Implementing these features is important, but is for now deferred to followup PRs. Many thanks to @ntBre, who contributed to this PR in a pairing session on Friday! ## Test Plan Assertions in existing mdtests are adjusted, and several new ones are added.
1 parent cba197e commit e87fee4

File tree

17 files changed

+927
-357
lines changed

17 files changed

+927
-357
lines changed

crates/red_knot_python_semantic/resources/mdtest/annotations/callable.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ References:
44

55
- <https://typing.readthedocs.io/en/latest/spec/callables.html#callable>
66

7-
TODO: Use `collections.abc` as importing from `typing` is deprecated but this requires support for
8-
`*` imports. See: <https://docs.python.org/3/library/typing.html#deprecated-aliases>.
7+
Note that `typing.Callable` is deprecated at runtime, in favour of `collections.abc.Callable` (see:
8+
<https://docs.python.org/3/library/typing.html#deprecated-aliases>). However, removal of
9+
`typing.Callable` is not currently planned, and the canonical location of the stub for the symbol in
10+
typeshed is still `typing.pyi`.
911

1012
## Invalid forms
1113

crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ reveal_type(DictSubclass.__mro__)
8181

8282
class SetSubclass(typing.Set): ...
8383

84-
# TODO: should have `Generic`, should not have `Unknown`
85-
# revealed: tuple[Literal[SetSubclass], Literal[set], Unknown, Literal[object]]
84+
# revealed: tuple[Literal[SetSubclass], Literal[set], Literal[MutableSet], Literal[AbstractSet], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(protocol), Literal[object]]
8685
reveal_type(SetSubclass.__mro__)
8786

8887
class FrozenSetSubclass(typing.FrozenSet): ...
@@ -114,8 +113,7 @@ reveal_type(DefaultDictSubclass.__mro__)
114113

115114
class DequeSubclass(typing.Deque): ...
116115

117-
# TODO: Should be (DequeSubclass, deque, MutableSequence, Sequence, Reversible, Collection, Sized, Iterable, Container, Generic, object)
118-
# revealed: tuple[Literal[DequeSubclass], Literal[deque], Unknown, Literal[object]]
116+
# revealed: tuple[Literal[DequeSubclass], Literal[deque], Literal[MutableSequence], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(protocol), Literal[object]]
119117
reveal_type(DequeSubclass.__mro__)
120118

121119
class OrderedDictSubclass(typing.OrderedDict): ...

crates/red_knot_python_semantic/resources/mdtest/attributes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ reveal_type(C().x) # revealed: str
551551
class C:
552552
def __init__(self) -> None:
553553
# error: [too-many-positional-arguments]
554+
# error: [invalid-argument-type]
554555
self.x: int = len(1, 2, 3)
555556
```
556557

crates/red_knot_python_semantic/resources/mdtest/expression/len.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,6 @@ reveal_type(len(SecondRequiredArgument())) # revealed: Literal[1]
229229
```py
230230
class NoDunderLen: ...
231231

232-
# TODO: Emit a diagnostic
232+
# error: [invalid-argument-type]
233233
reveal_type(len(NoDunderLen())) # revealed: int
234234
```

0 commit comments

Comments
 (0)