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

Class PossiblyUndefinedVariableVisitor

mypy/partially_defined.py:304–703  ·  view source on GitHub ↗

Detects the following cases: - A variable that's defined only part of the time. - If a variable is used before definition An example of a partial definition: if foo(): x = 1 print(x) # Error: "x" may be undefined. Example of a used before definition: x = y

Source from the content-addressed store, hash-verified

302
303
304class PossiblyUndefinedVariableVisitor(ExtendedTraverserVisitor):
305 """Detects the following cases:
306 - A variable that's defined only part of the time.
307 - If a variable is used before definition
308
309 An example of a partial definition:
310 if foo():
311 x = 1
312 print(x) # Error: "x" may be undefined.
313
314 Example of a used before definition:
315 x = y
316 y: int = 2
317
318 Note that this code does not detect variables not defined in any of the branches -- that is
319 handled by the semantic analyzer.
320 """
321
322 def __init__(
323 self,
324 msg: MessageBuilder,
325 type_map: dict[Expression, Type],
326 options: Options,
327 names: SymbolTable,
328 ) -> None:
329 self.msg = msg
330 self.type_map = type_map
331 self.options = options
332 self.builtins = SymbolTable()
333 builtins_mod = names.get("__builtins__", None)
334 if builtins_mod:
335 assert isinstance(builtins_mod.node, MypyFile)
336 self.builtins = builtins_mod.node.names
337 self.loops: list[Loop] = []
338 self.try_depth = 0
339 self.tracker = DefinedVariableTracker()
340 for name in implicit_module_attrs:
341 self.tracker.record_definition(name)
342
343 def var_used_before_def(self, name: str, context: Context) -> None:
344 if self.msg.errors.is_error_code_enabled(errorcodes.USED_BEFORE_DEF):
345 self.msg.var_used_before_def(name, context)
346
347 def variable_may_be_undefined(self, name: str, context: Context) -> None:
348 if self.msg.errors.is_error_code_enabled(errorcodes.POSSIBLY_UNDEFINED):
349 self.msg.variable_may_be_undefined(name, context)
350
351 def process_definition(self, name: str) -> None:
352 # Was this name previously used? If yes, it's a used-before-definition error.
353 if not self.tracker.in_scope(ScopeType.Class):
354 refs = self.tracker.pop_undefined_ref(name)
355 for ref in refs:
356 if self.loops:
357 self.variable_may_be_undefined(name, ref)
358 else:
359 self.var_used_before_def(name, ref)
360 else:
361 # Errors in class scopes are caught by the semantic analyzer.

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…