def test_augassign_attr(self): builder.parse(""" class Counter: v = 0 def inc(self): self.v += 1 """, __name__)
def test_asstuple(self): code = "a, b = range(2)" astroid = builder.parse(code) self.assertIn("b", astroid.locals) code = """ def visit_if(self, node): node.test, body = node.tests[0] """ astroid = builder.parse(code) self.assertIn("body", astroid["visit_if"].locals)
def test_asstuple(self): code = 'a, b = range(2)' astroid = builder.parse(code) self.assertIn('b', astroid.locals) code = ''' def visit_if(self, node): node.test, body = node.tests[0] ''' astroid = builder.parse(code) self.assertIn('body', astroid['visit_if'].locals)
def check_as_string_ast_equality(code): """ Check that as_string produces source code with exactly the same semantics as the source it was originally parsed from """ pre = builder.parse(code) post = builder.parse(pre.as_string()) pre_repr = pre.repr_tree() post_repr = post.repr_tree() assert pre_repr == post_repr assert pre.as_string().strip() == code.strip()
def test_inferred_dont_pollute(self): code = """ def func(a=None): a.custom_attr = 0 def func2(a={}): a.custom_attr = 0 """ builder.parse(code) nonetype = nodes.const_factory(None) self.assertNotIn("custom_attr", nonetype.locals) self.assertNotIn("custom_attr", nonetype.instance_attrs) nonetype = nodes.const_factory({}) self.assertNotIn("custom_attr", nonetype.locals) self.assertNotIn("custom_attr", nonetype.instance_attrs)
def test_inferred_dont_pollute(self): code = ''' def func(a=None): a.custom_attr = 0 def func2(a={}): a.custom_attr = 0 ''' builder.parse(code) nonetype = nodes.const_factory(None) # pylint: disable=no-member; Infers two potential values self.assertNotIn('custom_attr', nonetype.locals) self.assertNotIn('custom_attr', nonetype.instance_attrs) nonetype = nodes.const_factory({}) self.assertNotIn('custom_attr', nonetype.locals) self.assertNotIn('custom_attr', nonetype.instance_attrs)
def test_inferred_dont_pollute(self): code = ''' def func(a=None): a.custom_attr = 0 def func2(a={}): a.custom_attr = 0 ''' builder.parse(code) nonetype = nodes.const_factory(None) # pylint: disable=no-member; union type in const_factory, this shouldn't happen self.assertNotIn('custom_attr', nonetype.locals) self.assertNotIn('custom_attr', nonetype.instance_attrs) nonetype = nodes.const_factory({}) self.assertNotIn('custom_attr', nonetype.locals) self.assertNotIn('custom_attr', nonetype.instance_attrs)
def test_file_stream_physical(self): with open(__file__) as stream: astroid = builder.parse(stream.read()) with open(__file__, 'rb') as file_io: with astroid.stream() as stream: self.assertEqual([line.strip() for line in stream.read().splitlines()], [line.strip() for line in file_io.read().splitlines()])
def test_as_string(self): """check as_string for python syntax >= 2.7""" code = '''one_two = {1, 2} b = {v: k for (k, v) in enumerate('string')} cdd = {k for k in b}\n\n''' ast = builder.parse(code) self.assertMultiLineEqual(ast.as_string(), code)
def test_try_except(self): module = builder.parse(''' try: def exclusive_func2(): "docstring" except TypeError: def exclusive_func2(): "docstring" except: def exclusive_func2(): "docstring" else: def exclusive_func2(): "this one redefine the one defined line 42" ''') f1 = module.locals['exclusive_func2'][0] f2 = module.locals['exclusive_func2'][1] f3 = module.locals['exclusive_func2'][2] f4 = module.locals['exclusive_func2'][3] self.assertEqual(node_classes.are_exclusive(f1, f2), True) self.assertEqual(node_classes.are_exclusive(f1, f3), True) self.assertEqual(node_classes.are_exclusive(f1, f4), False) self.assertEqual(node_classes.are_exclusive(f2, f4), True) self.assertEqual(node_classes.are_exclusive(f3, f4), True) self.assertEqual(node_classes.are_exclusive(f3, f2), True) self.assertEqual(node_classes.are_exclusive(f2, f1), True) self.assertEqual(node_classes.are_exclusive(f4, f1), False) self.assertEqual(node_classes.are_exclusive(f4, f2), True)
def test_limit(self): code = ''' l = [a for a,b in list] a = 1 b = a a = None def func(): c = 1 ''' astroid = builder.parse(code, __name__) # a & b a = next(astroid.nodes_of_class(nodes.Name)) self.assertEqual(a.lineno, 2) if sys.version_info < (3, 0): self.assertEqual(len(astroid.lookup('b')[1]), 2) self.assertEqual(len(astroid.lookup('a')[1]), 3) b = astroid.locals['b'][1] else: self.assertEqual(len(astroid.lookup('b')[1]), 1) self.assertEqual(len(astroid.lookup('a')[1]), 2) b = astroid.locals['b'][0] stmts = a.lookup('a')[1] self.assertEqual(len(stmts), 1) self.assertEqual(b.lineno, 6) b_infer = b.infer() b_value = next(b_infer) self.assertEqual(b_value.value, 1) # c self.assertRaises(StopIteration, functools.partial(next, b_infer)) func = astroid.locals['func'][0] self.assertEqual(len(func.lookup('c')[1]), 1)
def test_newstyle_detection(self): data = ''' class A: "old style" class B(A): "old style" class C(object): "new style" class D(C): "new style" __metaclass__ = type class E(A): "old style" class F: "new style" ''' mod_ast = builder.parse(data, __name__) if six.PY3: self.assertTrue(mod_ast['A'].newstyle) self.assertTrue(mod_ast['B'].newstyle) self.assertTrue(mod_ast['E'].newstyle) else: self.assertFalse(mod_ast['A'].newstyle) self.assertFalse(mod_ast['B'].newstyle) self.assertFalse(mod_ast['E'].newstyle) self.assertTrue(mod_ast['C'].newstyle) self.assertTrue(mod_ast['D'].newstyle) self.assertTrue(mod_ast['F'].newstyle)
def test_parser(self): module = builder.parse(""" from dateutil.parser import parse d = parse('2000-01-01') """) d_type = next(module['d'].infer()) self.assertEqual(d_type.qname(), "datetime.datetime")
def test_set_comp_closure(self): astroid = builder.parse(""" ten = { var for var in range(10) } var """) var = astroid.body[1].value self.assertRaises(exceptions.NameInferenceError, var.inferred)
def astroid(self): try: return self.__class__.__dict__['CODE_Astroid'] except KeyError: module = builder.parse(self.CODE) self.__class__.CODE_Astroid = module return module
def astroid(self): try: return self.__class__.__dict__["CODE_Astroid"] except KeyError: astroid = builder.parse(self.CODE) self.__class__.CODE_Astroid = astroid return astroid
def test_newstyle_detection(self): data = """ class A: "old style" class B(A): "old style" class C(object): "new style" class D(C): "new style" __metaclass__ = type class E(A): "old style" class F: "new style" """ mod_ast = builder.parse(data, __name__) if six.PY3: self.assertTrue(mod_ast["A"].newstyle) self.assertTrue(mod_ast["B"].newstyle) self.assertTrue(mod_ast["E"].newstyle) else: self.assertFalse(mod_ast["A"].newstyle) self.assertFalse(mod_ast["B"].newstyle) self.assertFalse(mod_ast["E"].newstyle) self.assertTrue(mod_ast["C"].newstyle) self.assertTrue(mod_ast["D"].newstyle) self.assertTrue(mod_ast["F"].newstyle)
def test_type_comments_function(): module = builder.parse(''' def func(): # type: (int) -> str pass def func1(): # type: (int, int, int) -> (str, str) pass def func2(): # type: (int, int, str, List[int]) -> List[int] pass ''') expected_annotations = [ (["int"], astroid.Name, "str"), (["int", "int", "int"], astroid.Tuple, "(str, str)"), (["int", "int", "str", "List[int]"], astroid.Subscript, "List[int]"), ] for node, ( expected_args, expected_returns_type, expected_returns_string ) in zip(module.body, expected_annotations): assert node.type_comment_returns is not None assert node.type_comment_args is not None for expected_arg, actual_arg in zip(expected_args, node.type_comment_args): assert actual_arg.as_string() == expected_arg assert isinstance(node.type_comment_returns, expected_returns_type) assert node.type_comment_returns.as_string() == expected_returns_string
def test_starred_notation(self): astroid = builder.parse("*a, b = [1, 2, 3]", 'test', 'test') # Get the star node node = next(next(next(astroid.get_children()).get_children()).get_children()) self.assertTrue(isinstance(scope.assign_type(node), Assign))
def test_bad_import_inference(self): # Explication of bug '''When we import PickleError from nonexistent, a call to the infer method of this From node will be made by unpack_infer. inference.infer_from will try to import this module, which will fail and raise a InferenceException (by mixins.do_import_module). The infer_name will catch this exception and yield and Uninferable instead. ''' code = ''' try: from pickle import PickleError except ImportError: from nonexistent import PickleError try: pass except PickleError: pass ''' module = builder.parse(code) handler_type = module.body[1].handlers[0].type excs = list(node_classes.unpack_infer(handler_type)) # The number of returned object can differ on Python 2 # and Python 3. In one version, an additional item will # be returned, from the _pickle module, which is not # present in the other version. self.assertIsInstance(excs[0], nodes.ClassDef) self.assertEqual(excs[0].name, 'PickleError') self.assertIs(excs[-1], util.Uninferable)
def test_kwoargs(self): ast = builder.parse(''' def func(*, x): pass ''') args = ast['func'].args self.assertTrue(args.is_argument('x'))
def test_function_module_special(self): astroid = builder.parse(''' def initialize(linter): """initialize linter with checkers in this package """ package_load(linter, __path__[0]) ''', 'data.__init__') path = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == '__path__'][0] self.assertEqual(len(path.lookup('__path__')[1]), 1)
def test_argnames(self): if sys.version_info < (3, 0): code = 'def f(a, (b, c), *args, **kwargs): pass' else: code = 'def f(a, b, c, *args, **kwargs): pass' astroid = builder.parse(code, __name__) f = astroid.down().down() self.assertEqual(f.argnames(), ['a', 'b', 'c', 'args', 'kwargs'])
def test_type_comments_invalid_expression(): module = builder.parse(''' a, b = [1, 2, 3] # type: something completely invalid a, b = [1, 2, 3] # typeee: 2*+4 a, b = [1, 2, 3] # type: List[int ''') for node in module.body: assert node.type_annotation is None
def test_two_future_imports(self): mod = builder.parse( """ from __future__ import print_function from __future__ import absolute_import """ ) self.assertEqual(set(["print_function", "absolute_import"]), mod.future_imports)
def test_as_string(self): body = dedent(""" from abc import ABCMeta class Test(metaclass=ABCMeta): pass""") astroid = builder.parse(body) klass = astroid.body[1] self.assertEqual(klass.as_string(), '\n\nclass Test(metaclass=ABCMeta):\n pass\n')
def test_yield_from_as_string(self): body = dedent(""" def func(): (yield from iter([1, 2])) value = (yield from other()) """) astroid = builder.parse(body) func = astroid.body[0] self.assertEqual(func.as_string().strip(), body.strip())
def test_multiprocessing_manager(self): # Test that we have the proper attributes # for a multiprocessing.managers.SyncManager module = builder.parse(""" import multiprocessing manager = multiprocessing.Manager() queue = manager.Queue() joinable_queue = manager.JoinableQueue() event = manager.Event() rlock = manager.RLock() bounded_semaphore = manager.BoundedSemaphore() condition = manager.Condition() barrier = manager.Barrier() pool = manager.Pool() list = manager.list() dict = manager.dict() value = manager.Value() array = manager.Array() namespace = manager.Namespace() """) queue = next(module['queue'].infer()) self.assertEqual(queue.qname(), "{}.Queue".format(six.moves.queue.__name__)) joinable_queue = next(module['joinable_queue'].infer()) self.assertEqual(joinable_queue.qname(), "{}.Queue".format(six.moves.queue.__name__)) event = next(module['event'].infer()) event_name = "threading.{}".format("Event" if six.PY3 else "_Event") self.assertEqual(event.qname(), event_name) rlock = next(module['rlock'].infer()) rlock_name = "threading._RLock" self.assertEqual(rlock.qname(), rlock_name) bounded_semaphore = next(module['bounded_semaphore'].infer()) semaphore_name = "threading.{}".format( "BoundedSemaphore" if six.PY3 else "_BoundedSemaphore") self.assertEqual(bounded_semaphore.qname(), semaphore_name) pool = next(module['pool'].infer()) pool_name = "multiprocessing.pool.Pool" self.assertEqual(pool.qname(), pool_name) for attr in ('list', 'dict'): obj = next(module[attr].infer()) self.assertEqual(obj.qname(), "{}.{}".format(bases.BUILTINS, attr)) array = next(module['array'].infer()) self.assertEqual(array.qname(), "array.array") manager = next(module['manager'].infer()) # Verify that we have these attributes self.assertTrue(manager.getattr('start')) self.assertTrue(manager.getattr('shutdown'))
def test_yield_from_is_generator(self): body = dedent(""" def func(): yield from iter([1, 2]) """) astroid = builder.parse(body) func = astroid.body[0] self.assertIsInstance(func, FunctionDef) self.assertTrue(func.is_generator())
def test_gen_expr_var_scope(self): data = "l = list(n for n in range(10))\n" astroid = builder.parse(data, __name__) # n unavailable outside gen expr scope self.assertNotIn("n", astroid) # test n is inferable anyway n = test_utils.get_name_node(astroid, "n") self.assertIsNot(n.scope(), astroid) self.assertEqual([i.__class__ for i in n.infer()], [util.Uninferable.__class__])
def test_except_var_after_block_single(self) -> None: """When the variable bound to an exception in an except clause, it is NOT returned when that variable is used after the except block. """ code = """ try: 1 / 0 except NameError as e: pass print(e) """ astroid = builder.parse(code) x_name = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "e" ][0] _, stmts = x_name.lookup("e") self.assertEqual(len(stmts), 0)
def _multiprocessing_managers_transform(): return parse(""" import array import threading import multiprocessing.pool as pool import queue class Namespace(object): pass class Value(object): def __init__(self, typecode, value, lock=True): self._typecode = typecode self._value = value def get(self): return self._value def set(self, value): self._value = value def __repr__(self): return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value) value = property(get, set) def Array(typecode, sequence, lock=True): return array.array(typecode, sequence) class SyncManager(object): Queue = JoinableQueue = queue.Queue Event = threading.Event RLock = threading.RLock BoundedSemaphore = threading.BoundedSemaphore Condition = threading.Condition Barrier = threading.Barrier Pool = pool.Pool list = list dict = dict Value = Value Array = Array Namespace = Namespace __enter__ = lambda self: self __exit__ = lambda *args: args def start(self, initializer=None, initargs=None): pass def shutdown(self): pass """)
def test_type_comments_invalid_function_comments(): module = builder.parse( """ def func(): # type: something completely invalid pass def func1(): # typeee: 2*+4 pass def func2(): # type: List[int pass """ ) for node in module.body: assert node.type_comment_returns is None assert node.type_comment_args is None
def test_except_var_in_block(self) -> None: """When the variable bound to an exception in an except clause, it is returned when that variable is used inside the except block. """ code = """ try: 1 / 0 except ZeroDivisionError as e: print(e) """ astroid = builder.parse(code) x_name = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "e" ][0] _, stmts = x_name.lookup("e") self.assertEqual(len(stmts), 1) self.assertEqual(stmts[0].lineno, 4)
def test_linenumbering(self): ast = builder.parse(''' def func(a, b): pass x = lambda x: None ''') self.assertEqual(ast['func'].args.fromlineno, 2) self.assertFalse(ast['func'].args.is_statement) xlambda = next(ast['x'].infer()) self.assertEqual(xlambda.args.fromlineno, 4) self.assertEqual(xlambda.args.tolineno, 4) self.assertFalse(xlambda.args.is_statement) if sys.version_info < (3, 0): self.assertEqual(ast['func'].args.tolineno, 3) else: self.skipTest('FIXME http://bugs.python.org/issue10445 ' '(no line number on function args)')
def test_loopvar_hiding(self): astroid = builder.parse( """ x = 10 for x in range(5): print (x) if x > 0: print ('#' * x) """, __name__) xnames = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x' ] # inside the loop, only one possible assignment self.assertEqual(len(xnames[0].lookup('x')[1]), 1) # outside the loop, two possible assignments self.assertEqual(len(xnames[1].lookup('x')[1]), 2) self.assertEqual(len(xnames[2].lookup('x')[1]), 2)
def test_no_super_getattr(self): # This is a test for issue # https://bitbucket.org/logilab/astroid/issue/91, which tests # that UnboundMethod doesn't call super when doing .getattr. ast = builder.parse(""" class A(object): def test(self): pass meth = A.test """) node = next(ast["meth"].infer()) with self.assertRaises(exceptions.AttributeInferenceError): node.getattr("__missssing__") name = node.getattr("__name__")[0] self.assertIsInstance(name, nodes.Const) self.assertEqual(name.value, "test")
def test_enum_multiple_base_classes(self): module = builder.parse(""" import enum class Mixin: pass class MyEnum(Mixin, enum.Enum): one = 1 """) enumeration = next(module['MyEnum'].infer()) one = enumeration['one'] clazz = one.getattr('__class__')[0] self.assertTrue( clazz.is_subtype_of('.Mixin'), 'Enum instance should share base classes with generating class')
def test_generator_attributes(self): tree = builder.parse( """ def count(): "test" yield 0 iterer = count() num = iterer.next() """ ) next_node = tree.body[2].value.func gener = next_node.expr.inferred()[0] self.assertIsInstance(gener.getattr("__next__")[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr("send")[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr("throw")[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr("close")[0], nodes.FunctionDef)
def test_dict_comp_nested(self) -> None: astroid = builder.parse( """ x = {i: {i: j for j in range(20)} for i in range(10)} x3 = [{i + j for j in range(20)} # Can't do nested sets for i in range(10)] """, __name__, ) xnames = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "i" ] self.assertEqual(len(xnames[0].lookup("i")[1]), 1) self.assertEqual(xnames[0].lookup("i")[1][0].lineno, 3) self.assertEqual(len(xnames[1].lookup("i")[1]), 1) self.assertEqual(xnames[1].lookup("i")[1][0].lineno, 3)
def infer_dataclass_field_call( node: Call, ctx: Optional[context.InferenceContext] = None ) -> Generator: """Inference tip for dataclass field calls.""" if not isinstance(node.parent, (AnnAssign, Assign)): raise UseInferenceDefault result = _get_field_default(node) if not result: yield Uninferable else: default_type, default = result if default_type == "default": yield from default.infer(context=ctx) else: new_call = parse(default.as_string()).body[0].value new_call.parent = node.parent yield from new_call.infer(context=ctx)
def test_get_children_order(): class OrderVisitor: def __init__(self): for node_class in nodes.ALL_NODE_CLASSES: visit_name = 'visit_' + node_class.__name__.lower() self.__dict__[visit_name] = self.visit self.position = (0, 0) def visit(self, node): if (isinstance(node, node_classes.BinOp) and (isinstance(node.left, node_classes.BinOp) or isinstance(node.right, node_classes.BinOp))): # The outer BinOp in nested BinOps has incorrect col_offset # at the col_offset of the operator return if isinstance(node, node_classes.ExceptHandler): # Exception handler name node has incorrect col_offset of 0 return # All other node classes have correct positions so check they # are yielded in position order for child in node.get_children(): if child.lineno is not None: position = (child.lineno, child.col_offset) assert self.position <= position, child self.position = position child.accept(self) ast = builder.parse(''' def func(a: bool, b=1, *c: str, d: str, e=2, **kwargs: int): return b if a else e a = 1 + 2 + 3 try: func() except Exception as e: pass ''') ast.accept(OrderVisitor()) for module in ['data/module.py', 'data/module2.py']: resources.build_file(module).accept(OrderVisitor())
def test_if_assign(self) -> None: """Assignment in if statement is added to lookup results, but does not replace prior assignments. """ code = """ def f(b): x = 10 if b: x = 100 print(x) """ astroid = builder.parse(code) x_name = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "x" ][0] _, stmts = x_name.lookup("x") self.assertEqual(len(stmts), 2) self.assertCountEqual([stmt.lineno for stmt in stmts], [3, 5])
def test_except_assign_in_block(self) -> None: """When a variable is assigned in an except block, it is returned when that variable is used in the except block. """ code = """ try: 1 / 0 except ZeroDivisionError as e: x = 10 print(x) """ astroid = builder.parse(code) x_name = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "x" ][0] _, stmts = x_name.lookup("x") self.assertEqual(len(stmts), 1) self.assertEqual(stmts[0].lineno, 5)
def test_generator_attributes(self): tree = builder.parse(""" def count(): "test" yield 0 iterer = count() num = iterer.next() """) next_node = tree.body[2].value.func gener = next_node.expr.inferred()[0] if sys.version_info < (3, 0): self.assertIsInstance(gener.getattr('next')[0], nodes.FunctionDef) else: self.assertIsInstance(gener.getattr('__next__')[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr('send')[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr('throw')[0], nodes.FunctionDef) self.assertIsInstance(gener.getattr('close')[0], nodes.FunctionDef)
def test_try_finally_25_lineno(self): astroid = builder.parse( """ try: print (a) except: pass finally: print ("bouh") """, __name__, ) try_ = astroid.body[0] self.assertEqual(try_.fromlineno, 2) self.assertEqual(try_.tolineno, 7) self.assertEqual(try_.blockstart_tolineno, 2) self.assertEqual(try_.finalbody[0].fromlineno, 7) # XXX self.assertEqual(try_.finalbody[0].tolineno, 7)
def test_decorated_function_lineno(self): astroid = builder.parse(''' @decorator def function( arg): print (arg) ''', __name__) function = astroid['function'] # XXX discussable, but that's what is expected by pylint right now self.assertEqual(function.fromlineno, 3) self.assertEqual(function.tolineno, 5) self.assertEqual(function.decorators.fromlineno, 2) self.assertEqual(function.decorators.tolineno, 2) if sys.version_info < (3, 0): self.assertEqual(function.blockstart_tolineno, 4) else: self.skipTest('FIXME http://bugs.python.org/issue10445 ' '(no line number on function args)')
def test_list_comps(self): astroid = builder.parse( """ print ([ i for i in range(10) ]) print ([ i for i in range(10) ]) print ( list( i for i in range(10) ) ) """, __name__, ) xnames = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "i" ] self.assertEqual(len(xnames[0].lookup("i")[1]), 1) self.assertEqual(xnames[0].lookup("i")[1][0].lineno, 2) self.assertEqual(len(xnames[1].lookup("i")[1]), 1) self.assertEqual(xnames[1].lookup("i")[1][0].lineno, 3) self.assertEqual(len(xnames[2].lookup("i")[1]), 1) self.assertEqual(xnames[2].lookup("i")[1][0].lineno, 4)
def test_linenumbering(self): ast = builder.parse( """ def func(a, b): pass x = lambda x: None """ ) self.assertEqual(ast["func"].args.fromlineno, 2) self.assertFalse(ast["func"].args.is_statement) xlambda = next(ast["x"].infer()) self.assertEqual(xlambda.args.fromlineno, 4) self.assertEqual(xlambda.args.tolineno, 4) self.assertFalse(xlambda.args.is_statement) self.skipTest( "FIXME http://bugs.python.org/issue10445 " "(no line number on function args)" )
def test_explicit___name__(self): code = ''' class Pouet: __name__ = "pouet" p1 = Pouet() class PouetPouet(Pouet): pass p2 = Pouet() class NoName: pass p3 = NoName() ''' astroid = builder.parse(code, __name__) p1 = next(astroid['p1'].infer()) self.assertTrue(p1.getattr('__name__')) p2 = next(astroid['p2'].infer()) self.assertTrue(p2.getattr('__name__')) self.assertTrue(astroid['NoName'].getattr('__name__')) p3 = next(astroid['p3'].infer()) self.assertRaises(exceptions.AttributeInferenceError, p3.getattr, '__name__')
def test_not_exclusive(self): module = builder.parse( """ x = 10 for x in range(5): print (x) if x > 0: print ('#' * x) """, __name__, __file__) xass1 = module.locals['x'][0] assert xass1.lineno == 2 xnames = [ n for n in module.nodes_of_class(nodes.Name) if n.name == 'x' ] assert len(xnames) == 3 assert xnames[1].lineno == 6 self.assertEqual(node_classes.are_exclusive(xass1, xnames[1]), False) self.assertEqual(node_classes.are_exclusive(xass1, xnames[2]), False)
def test_if_assigns_same_branch(self) -> None: """When if branch has multiple assignment statements, only the last one is added. """ code = """ def f(b): x = 10 if b: x = 100 x = 1000 print(x) """ astroid = builder.parse(code) x_name = [ n for n in astroid.nodes_of_class(nodes.Name) if n.name == "x" ][0] _, stmts = x_name.lookup("x") self.assertEqual(len(stmts), 2) self.assertCountEqual([stmt.lineno for stmt in stmts], [3, 6])
def test_try_except_lineno(self): astroid = builder.parse(''' try: print (a) except: pass else: print ("bouh") ''', __name__) try_ = astroid.body[0] self.assertEqual(try_.fromlineno, 2) self.assertEqual(try_.tolineno, 7) self.assertEqual(try_.blockstart_tolineno, 2) self.assertEqual(try_.orelse[0].fromlineno, 7) # XXX self.assertEqual(try_.orelse[0].tolineno, 7) hdlr = try_.handlers[0] self.assertEqual(hdlr.fromlineno, 4) self.assertEqual(hdlr.tolineno, 5) self.assertEqual(hdlr.blockstart_tolineno, 4)
def test_global_delete(self): code = """ def run2(): f = Frobble() class Frobble: pass Frobble.mumble = True del Frobble def run1(): f = Frobble() """ astroid = builder.parse(code, __name__) stmts = astroid["run2"].lookup("Frobbel")[1] self.assertEqual(len(stmts), 0) stmts = astroid["run1"].lookup("Frobbel")[1] self.assertEqual(len(stmts), 0)
def test_static_method_lookup(self) -> None: code = """ class FileA: @staticmethod def funcA(): return 4 class Test: FileA = [1,2,3] def __init__(self): print (FileA.funcA()) """ astroid = builder.parse(code, __name__) it = astroid["Test"]["__init__"].ilookup("FileA") obj = next(it) self.assertIsInstance(obj, nodes.ClassDef) self.assertRaises(StopIteration, functools.partial(next, it))
def test_static_method_lookup(self): code = ''' class FileA: @staticmethod def funcA(): return 4 class Test: FileA = [1,2,3] def __init__(self): print (FileA.funcA()) ''' astroid = builder.parse(code, __name__) it = astroid['Test']['__init__'].ilookup('FileA') obj = next(it) self.assertIsInstance(obj, nodes.ClassDef) self.assertRaises(StopIteration, functools.partial(next, it))
def test_global_delete(self): code = ''' def run2(): f = Frobble() class Frobble: pass Frobble.mumble = True del Frobble def run1(): f = Frobble() ''' astroid = builder.parse(code, __name__) stmts = astroid['run2'].lookup('Frobbel')[1] self.assertEqual(len(stmts), 0) stmts = astroid['run1'].lookup('Frobbel')[1] self.assertEqual(len(stmts), 0)
def test_dict_comps(self): astroid = builder.parse( """ print ({ i: j for i in range(10) for j in range(10) }) print ({ i: j for i in range(10) for j in range(10) }) """, __name__, ) xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == "i"] self.assertEqual(len(xnames[0].lookup("i")[1]), 1) self.assertEqual(xnames[0].lookup("i")[1][0].lineno, 2) self.assertEqual(len(xnames[1].lookup("i")[1]), 1) self.assertEqual(xnames[1].lookup("i")[1][0].lineno, 3) xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == "j"] self.assertEqual(len(xnames[0].lookup("i")[1]), 1) self.assertEqual(xnames[0].lookup("i")[1][0].lineno, 2) self.assertEqual(len(xnames[1].lookup("i")[1]), 1) self.assertEqual(xnames[1].lookup("i")[1][0].lineno, 3)
def test_globals(self): data = ''' CSTE = 1 def update_global(): global CSTE CSTE += 1 def global_no_effect(): global CSTE2 print (CSTE) ''' astroid = builder.parse(data, __name__) self.assertEqual(len(astroid.getattr('CSTE')), 2) self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssignName) self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2) self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6) with self.assertRaises(exceptions.AttributeInferenceError): astroid.getattr('CSTE2') with self.assertRaises(exceptions.InferenceError): next(astroid['global_no_effect'].ilookup('CSTE2'))
def test_explicit___name__(self): code = """ class Pouet: __name__ = "pouet" p1 = Pouet() class PouetPouet(Pouet): pass p2 = Pouet() class NoName: pass p3 = NoName() """ astroid = builder.parse(code, __name__) p1 = next(astroid["p1"].infer()) self.assertTrue(p1.getattr("__name__")) p2 = next(astroid["p2"].infer()) self.assertTrue(p2.getattr("__name__")) self.assertTrue(astroid["NoName"].getattr("__name__")) p3 = next(astroid["p3"].infer()) self.assertRaises(exceptions.AttributeInferenceError, p3.getattr, "__name__")