MCPcopy Index your code
hub / github.com/python/mypy / SemanticAnalyzerPreAnalysis

Class SemanticAnalyzerPreAnalysis

mypy/semanal_pass1.py:30–159  ·  view source on GitHub ↗

Analyze reachability of blocks and imports and other local things. This runs before semantic analysis, so names have not been bound. Imports are also not resolved yet, so we can only access the current module. This determines static reachability of blocks and imports due to version and

Source from the content-addressed store, hash-verified

28
29
30class SemanticAnalyzerPreAnalysis(TraverserVisitor):
31 """Analyze reachability of blocks and imports and other local things.
32
33 This runs before semantic analysis, so names have not been bound. Imports are
34 also not resolved yet, so we can only access the current module.
35
36 This determines static reachability of blocks and imports due to version and
37 platform checks, among others.
38
39 The main entry point is 'visit_file'.
40
41 Reachability of imports needs to be determined very early in the build since
42 this affects which modules will ultimately be processed.
43
44 Consider this example:
45
46 import sys
47
48 def do_stuff() -> None:
49 if sys.version_info >= (3, 11):
50 import xyz # Only available in Python 3.11+
51 xyz.whatever()
52 ...
53
54 The block containing 'import xyz' is unreachable in Python 3.10 mode. The import
55 shouldn't be processed in Python 3.10 mode, even if the module happens to exist.
56 """
57
58 def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) -> None:
59 self.platform = options.platform
60 self.cur_mod_id = mod_id
61 self.cur_mod_node = file
62 self.options = options
63 self.is_global_scope = True
64 self.skipped_lines: set[int] = set()
65
66 for i, defn in enumerate(file.defs):
67 defn.accept(self)
68 if isinstance(defn, AssertStmt) and assert_will_always_fail(defn, options):
69 # We've encountered an assert that's always false,
70 # e.g. assert sys.platform == 'lol'. Truncate the
71 # list of statements. This mutates file.defs too.
72 if i < len(file.defs) - 1:
73 next_def, last = file.defs[i + 1], file.defs[-1]
74 if last.end_line is not None:
75 # We are on a Python version recent enough to support end lines.
76 self.skipped_lines |= set(range(next_def.line, last.end_line + 1))
77 file.imports = [
78 i for i in file.imports if (i.line, i.column) <= (defn.line, defn.column)
79 ]
80 del file.defs[i + 1 :]
81 break
82 file.skipped_lines = self.skipped_lines
83
84 def visit_func_def(self, node: FuncDef) -> None:
85 old_global_scope = self.is_global_scope
86 self.is_global_scope = False
87 super().visit_func_def(node)

Callers 1

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…