mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
[ty] Add special-cased inference for __import__(name)
and importlib.import_module(name)
(#19008)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
This commit is contained in:
parent
de1f8177be
commit
e7aadfc28b
5 changed files with 185 additions and 51 deletions
|
@ -0,0 +1,91 @@
|
|||
# `__import__`
|
||||
|
||||
The global function `__import__()` allows for dynamic imports.
|
||||
|
||||
A few of its call patterns are recognized and resolved to literal module types instead of the
|
||||
general `ModuleType`, which is used as the fallback for unrecognized call patterns and unresolvable
|
||||
names.
|
||||
|
||||
## Basic
|
||||
|
||||
```py
|
||||
reveal_type(__import__("sys")) # revealed: <module 'sys'>
|
||||
reveal_type(__import__(name="shutil")) # revealed: <module 'shutil'>
|
||||
|
||||
reveal_type(__import__("nonexistent")) # revealed: ModuleType
|
||||
reveal_type(__import__("collections.abc")) # revealed: ModuleType
|
||||
reveal_type(__import__("fnmatch", globals())) # revealed: ModuleType
|
||||
reveal_type(__import__("shelve", fromlist=[""])) # revealed: ModuleType
|
||||
```
|
||||
|
||||
## Unions
|
||||
|
||||
The specified name must be a string literal. Different modules must be imported explicitly.
|
||||
|
||||
```py
|
||||
def _(flag: bool):
|
||||
if flag:
|
||||
name = "sys"
|
||||
else:
|
||||
name = "os"
|
||||
|
||||
reveal_type(name) # revealed: Literal["sys", "os"]
|
||||
reveal_type(__import__(name)) # revealed: ModuleType
|
||||
|
||||
if flag:
|
||||
module = __import__("heapq")
|
||||
else:
|
||||
module = __import__("curses")
|
||||
|
||||
reveal_type(module) # revealed: <module 'heapq'> | <module 'curses'>
|
||||
```
|
||||
|
||||
## Nested modules
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
# TODO: Should be `<module 'a'>`
|
||||
a = reveal_type(__import__("a.b.c")) # revealed: ModuleType
|
||||
|
||||
# TODO: Should be `int`, `str`, `bytes`
|
||||
# error: [unresolved-attribute]
|
||||
reveal_type(a.a) # revealed: Unknown
|
||||
# error: [unresolved-attribute]
|
||||
reveal_type(a.b.b) # revealed: Unknown
|
||||
# error: [unresolved-attribute]
|
||||
reveal_type(a.b.c.c) # revealed: Unknown
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
||||
```py
|
||||
a: int = 1
|
||||
```
|
||||
|
||||
`a/b/__init__.py`:
|
||||
|
||||
```py
|
||||
b: str = ""
|
||||
```
|
||||
|
||||
`a/b/c.py`:
|
||||
|
||||
```py
|
||||
c: bytes = b""
|
||||
```
|
||||
|
||||
## `importlib.import_module()`
|
||||
|
||||
`importlib.import_module()` has similar semantics, but returns the submodule.
|
||||
|
||||
```py
|
||||
import importlib
|
||||
|
||||
reveal_type(importlib.import_module("bisect")) # revealed: <module 'bisect'>
|
||||
reveal_type(importlib.import_module("os.path")) # revealed: <module 'os.path'>
|
||||
reveal_type(importlib.import_module(name="tempfile")) # revealed: <module 'tempfile'>
|
||||
|
||||
reveal_type(importlib.import_module("nonexistent")) # revealed: ModuleType
|
||||
reveal_type(importlib.import_module("config", "logging")) # revealed: ModuleType
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue