def test_message_loop_complex(self): src = """ y = 0 x = 10 for y in range(1, 10): x = func(y) print(x) x = 10 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_y, assign_x1, assign_x2, assign_x3 = mod.nodes_of_class( astroid.Assign) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='redundant-assignment', node=assign_y, ), pylint.testutils.Message( msg_id='redundant-assignment', node=assign_x1, ), ): self.checker.visit_assign(assign_y) self.checker.visit_assign(assign_x1) self.checker.visit_assign(assign_x2) self.checker.visit_assign(assign_x3)
def test_message_complex(self): src = """ def test(x): if True: y = 10 else: for j in range(10): if j > 10: break else: y = 10 return y """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, _, name_node_y = mod.nodes_of_class(astroid.Name) self.checker.visit_functiondef(func_node) with self.assertAddsMessages( pylint.testutils.Message( msg_id='possibly-undefined', node=name_node_y, ), ): self.checker.visit_name(name_node_y)
def main(filepath: str) -> None: filename = os.path.splitext(os.path.basename(filepath))[0] mod = AstroidBuilder().file_build(filepath) visitor = CFGVisitor() mod.accept(visitor) display(visitor.cfgs, filename)
def build_cfgs( src: str ) -> Dict[Union[nodes.FunctionDef, nodes.Module], ControlFlowGraph]: mod = astroid.parse(src) t = CFGVisitor() mod.accept(t) return t.cfgs
def build_cfg(src: str, is_function: Optional[bool] = False) -> ControlFlowGraph: """<is_function> == True guarantees that the function node is the first node in the module.""" mod = astroid.parse(src) t = CFGVisitor() mod.accept(t) if is_function: return t.cfgs[mod.body[0]] return t.cfgs[mod]
def test_no_message_loop(self): src = """ y = 5 while y > 5: x = 10 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) _, assign_x, *_ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_assign(assign_x)
def test_no_messages_simple(self): src = """ x = 10 print(x) x = 10 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_1, *_ = mod.nodes_of_class(astroid.Assign) with self.assertNoMessages(): self.checker.visit_module(mod) self.checker.visit_assign(assign_1)
def test_no_message_loop_(self): src = """ y = 0 for y in range(1, 10): x = 10 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) _, assign_x, *_ = mod.nodes_of_class(astroid.Assign) print(assign_x.as_string()) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_assign(assign_x)
def test_augassign_simple_no_message(self): src = """ y_pos = 5 y_pos += 10 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) self.checker.visit_module(mod) with self.assertNoMessages(): for node in mod.nodes_of_class(astroid.Assign): self.checker.visit_assign(node) for node in mod.nodes_of_class(astroid.AugAssign): self.checker.visit_augassign(node)
def test_no_messages_with_args(self): src = """ def test(x): if True: x = 10 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, name_node_x = mod.nodes_of_class(astroid.Name) with self.assertNoMessages(): self.checker.visit_functiondef(func_node) self.checker.visit_name(name_node_x)
def test_with_comprehension(self): src = """ def func(lst): test = [x for x in lst] x = 0 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] # expression `x` at line `test = ...` name_node_x = next(func_node.nodes_of_class(astroid.Name)) self.checker.visit_functiondef(func_node) with self.assertNoMessages(): self.checker.visit_name(name_node_x)
def test_with_dict_comprehension(self): src = """ def func(lst): test = {key:val for key, val in lst} key = 0 print(key) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] # expression `key` at line `test = ...` name_node_key = next(func_node.nodes_of_class(nodes.Name)) self.checker.visit_functiondef(func_node) with self.assertNoMessages(): self.checker.visit_name(name_node_key)
def test_no_messages_if_else_with_ann_assign(self): src = """ def test(x): if True: y: int = 10 else: y = 20 print(y) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, _, name_node_y = mod.nodes_of_class(astroid.Name) with self.assertNoMessages(): self.checker.visit_functiondef(func_node) self.checker.visit_name(name_node_y)
def test_no_messages_with_nonlocal(self): src = """ def test(x): x = 10 nonlocal y if True: y = 10 print(y) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] __, name_node_y = mod.nodes_of_class(nodes.Name) with self.assertNoMessages(): self.checker.visit_functiondef(func_node) self.checker.visit_name(name_node_y)
def test_augassign_redundant(self): src = """ y_pos = 5 y_pos += 10 y_pos = 10 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) augassign_node, *_ = mod.nodes_of_class(astroid.AugAssign) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='redundant-assignment', node=augassign_node, )): self.checker.visit_augassign(augassign_node)
def test_message_simple(self): src = """ x = 10 x = 230 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_1, _ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='redundant-assignment', node=assign_1, ), ): self.checker.visit_assign(assign_1)
def test_no_message_function_def(self): src = """ x = 10 if False: x = 20 else: def func(): x = 1 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_x, *_ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_assign(assign_x)
def test_no_message_loop_complex(self): src = """ x = 10 for y in range(1, 10): x = func(y) print(x) x = x - 1 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_x1, assign_x2, assign_x3 = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_assign(assign_x1) self.checker.visit_assign(assign_x2) self.checker.visit_assign(assign_x3)
def test_no_messages_simple(self): src = """ def test(x): x = 10 if True: return x return x """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] name_node_a, name_node_b = mod.nodes_of_class(astroid.Name) with self.assertNoMessages(): self.checker.visit_module(mod) self.checker.visit_functiondef(func_node) self.checker.visit_name(name_node_a) self.checker.visit_name(name_node_b)
def test_message_with_func_name(self): src = """ if True: pass else: y = lambda: 20 y() """ mod = astroid.parse(src) mod.accept(CFGVisitor()) *_, name_node_y = mod.nodes_of_class(astroid.Name) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='possibly-undefined', node=name_node_y, ), ): self.checker.visit_name(name_node_y)
def test_no_message_if_complex(self): src = """ x = 10 y = 5 if y > 5: x = 20 elif y > 50: x = 15 else: pass print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_x, *_ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_assign(assign_x)
def test_message_with_args(self): src = """ def test(x): if True: del x print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, name_node_x = mod.nodes_of_class(astroid.Name) self.checker.visit_functiondef(func_node) with self.assertAddsMessages( pylint.testutils.Message( msg_id='possibly-undefined', node=name_node_x, ), ): self.checker.visit_name(name_node_x)
def test_message_with_del_simple(self): src = """ def test(x): y = 0 del y print(y) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, name_node_y = mod.nodes_of_class(nodes.Name) self.checker.visit_functiondef(func_node) with self.assertAddsMessages( pylint.testutils.MessageTest(msg_id="possibly-undefined", node=name_node_y), ignore_position=True, ): self.checker.visit_name(name_node_y)
def test_no_messages_with_class_def(self): """This example is a false negative due to how class definitions are represented in the control flow graph.""" src = """ class A: y = 10 if True: x = 10 else: y = 20 print(y) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) _, name_node_y = mod.nodes_of_class(astroid.Name) self.checker.visit_module(mod) with self.assertNoMessages(): self.checker.visit_name(name_node_y)
def test_assign(self): src = """ def func(): if False: x = 10 x = x + 1 """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] name_node_x = next(func_node.nodes_of_class(astroid.Name)) print(list(func_node.nodes_of_class(astroid.Name))) self.checker.visit_functiondef(func_node) with self.assertAddsMessages( pylint.testutils.Message( msg_id='possibly-undefined', node=name_node_x, )): self.checker.visit_name(name_node_x)
def test_no_messages_with_import_from(self): src = """ from random import j y = 0 if y > 10: j = 10 else: y = 5 print(j) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) name_node_y, name_node_print, name_node_j = mod.nodes_of_class( astroid.Name) with self.assertNoMessages(): self.checker.visit_module(mod) self.checker.visit_name(name_node_y) self.checker.visit_name(name_node_print) self.checker.visit_name(name_node_j)
def test_message_scope(self): src = """ x = 25 def func(): def func2(): print(x - 1) func2() x = 10 func() """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_x, *_ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='redundant-assignment', node=assign_x, )): self.checker.visit_assign(assign_x)
def test_multiple_messages_simple(self): src = """ if True: y: int = 10 else: x = 10 print(x and y) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) _, _, name_node_x, name_node_y = mod.nodes_of_class(nodes.Name) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.MessageTest(msg_id="possibly-undefined", node=name_node_y), pylint.testutils.MessageTest(msg_id="possibly-undefined", node=name_node_x), ignore_position=True, ): self.checker.visit_name(name_node_y) self.checker.visit_name(name_node_x)
def test_message_if_stmt(self): src = """ x = 10 y = 5 if y > 5: x = 20 else: x = 15 print(x) """ mod = astroid.parse(src) mod.accept(CFGVisitor()) assign_x, *_ = mod.nodes_of_class(astroid.Assign) self.checker.visit_module(mod) with self.assertAddsMessages( pylint.testutils.Message( msg_id='redundant-assignment', node=assign_x, ), ): self.checker.visit_assign(assign_x)
def test_no_messages_complex(self): src = """ def test(x): if True: y = 10 else: for j in range(10): if j > 10: y = 10 break else: y = 10 return y """ mod = astroid.parse(src) mod.accept(CFGVisitor()) func_node = mod.body[0] _, _, name_node_y = mod.nodes_of_class(astroid.Name) with self.assertNoMessages(): self.checker.visit_functiondef(func_node) self.checker.visit_name(name_node_y)