Expand description
Import-resolution table: import, from … import, and … as … forms.
Imports::build walks the entire file, recursing into function and class
bodies (nested suites), and fills a map from local name → fully-qualified
module path (a dot-joined string). Function-local imports are therefore
resolved file-wide (an intentional over-approximation for a syntactic tool).
This mirrors the Rust frontend’s imports module and feeds the call-site
detector so it can identify high-risk imported symbols.
§Mapping rules
| Source form | local key | resolved path |
|---|---|---|
import os | os | "os" |
import a.b.c | a | "a.b.c" |
import numpy as np | np | "numpy" |
from subprocess import run | run | "subprocess.run" |
from m import n as p | p | "m.n" |
For import a.b.c (no alias) the local key is the root component (a).
Aliases always win: import a.b as x → key x, path "a.b".
§has_dynamic
Set to true when importlib appears as an imported module name or
__import__ appears as an imported name inside a from … import statement.
This detects dynamic-import infrastructure being imported, not call-site
usage; actual call-site detection (e.g. importlib.import_module(…)) is
handled by detect/risk.rs.
Structs§
- Imports
- A resolved import table built from import statements anywhere in a
Module(recursing into nested function and class bodies for file-wide resolution).
Functions§
- module_
bindings - Collect the names introduced by module top-level statements of
module: assignment targets (x = …,x: T = …, and destructureda, b = …/[x, y] = …/*rest, last = …),defnames, andclassnames. Only the module body is scanned; names bound inside function bodies are not collected. A write whose root is one of these — when it is not a local/param/global- declared/import in the writing function — is a write to module-shared state, escalated toglobal.mutation(the Python analog of #29).