def walk(self, astroid: nodes.NodeNG) -> None: """Call visit events of astroid checkers for the given node, recurse on its children, then leave events. """ cid = astroid.__class__.__name__.lower() # Detect if the node is a new name for a deprecated alias. # In this case, favour the methods for the deprecated # alias if any, in order to maintain backwards # compatibility. visit_events: Sequence[AstCallback] = self.visit_events.get(cid, ()) leave_events: Sequence[AstCallback] = self.leave_events.get(cid, ()) try: if astroid.is_statement: self.nbstatements += 1 # generate events for this node on each checker for callback in visit_events: callback(astroid) # recurse on children for child in astroid.get_children(): self.walk(child) for callback in leave_events: callback(astroid) except Exception: if self.exception_msg is False: file = getattr(astroid.root(), "file", None) print( f"Exception on node {repr(astroid)} in file '{file}'", file=sys.stderr, ) traceback.print_exc() self.exception_msg = True raise
def visit_default(self, node: nodes.NodeNG) -> None: """Check the node line number and check it if not yet done.""" if not node.is_statement: return if not node.root().pure_python: return prev_sibl = node.previous_sibling() if prev_sibl is not None: prev_line = prev_sibl.fromlineno # The line on which a 'finally': occurs in a 'try/finally' # is not directly represented in the AST. We infer it # by taking the last line of the body and adding 1, which # should be the line of finally: elif (isinstance(node.parent, nodes.TryFinally) and node in node.parent.finalbody): prev_line = node.parent.body[0].tolineno + 1 elif isinstance(node.parent, nodes.Module): prev_line = 0 else: prev_line = node.parent.statement(future=True).fromlineno line = node.fromlineno assert line, node if prev_line == line and self._visited_lines.get(line) != 2: self._check_multi_statement_line(node, line) return if line in self._visited_lines: return try: tolineno = node.blockstart_tolineno except AttributeError: tolineno = node.tolineno assert tolineno, node lines = [] for line in range(line, tolineno + 1): self._visited_lines[line] = 1 try: lines.append(self._lines[line].rstrip()) except KeyError: lines.append("")
def _msg_postponed_eval_hint(self, node: nodes.NodeNG) -> str: """Message hint if postponed evaluation isn't enabled.""" if self._py310_plus or "annotations" in node.root().future_imports: return "" return ". Add 'from __future__ import annotations' as well"