| # Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
| # Copyright (c) 2014-2016 Claudiu Popa <pcmanticore@gmail.com> |
| # Copyright (c) 2014-2015 Google, Inc. |
| # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com> |
| |
| # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
| # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
| |
| """tests for the astroid builder and rebuilder module""" |
| |
| import os |
| import sys |
| import unittest |
| |
| import six |
| |
| from astroid import builder |
| from astroid import exceptions |
| from astroid import manager |
| from astroid import nodes |
| from astroid import raw_building |
| from astroid import test_utils |
| from astroid import util |
| from astroid.tests import resources |
| |
| MANAGER = manager.AstroidManager() |
| BUILTINS = six.moves.builtins.__name__ |
| |
| |
| class FromToLineNoTest(unittest.TestCase): |
| |
| def setUp(self): |
| self.astroid = builder.parse(''' |
| """A multiline string |
| """ |
| |
| function('aeozrijz\ |
| earzer', hop) |
| # XXX write test |
| x = [i for i in range(5) |
| if i % 4] |
| |
| fonction(1, |
| 2, |
| 3, |
| 4) |
| |
| def definition(a, |
| b, |
| c): |
| return a + b + c |
| |
| class debile(dict, |
| object): |
| pass |
| |
| if aaaa: pass |
| else: |
| aaaa,bbbb = 1,2 |
| aaaa,bbbb = bbbb,aaaa |
| # XXX write test |
| hop = \ |
| aaaa |
| |
| |
| __revision__.lower(); |
| ''') |
| |
| def test_callfunc_lineno(self): |
| stmts = self.astroid.body |
| # on line 4: |
| # function('aeozrijz\ |
| # earzer', hop) |
| discard = stmts[0] |
| self.assertIsInstance(discard, nodes.Expr) |
| self.assertEqual(discard.fromlineno, 5) |
| self.assertEqual(discard.tolineno, 5) |
| callfunc = discard.value |
| self.assertIsInstance(callfunc, nodes.Call) |
| self.assertEqual(callfunc.fromlineno, 5) |
| self.assertEqual(callfunc.tolineno, 5) |
| name = callfunc.func |
| self.assertIsInstance(name, nodes.Name) |
| self.assertEqual(name.fromlineno, 5) |
| self.assertEqual(name.tolineno, 5) |
| strarg = callfunc.args[0] |
| self.assertIsInstance(strarg, nodes.Const) |
| if hasattr(sys, 'pypy_version_info'): |
| lineno = 4 |
| else: |
| lineno = 5 # no way for this one in CPython (is 4 actually) |
| self.assertEqual(strarg.fromlineno, lineno) |
| self.assertEqual(strarg.tolineno, lineno) |
| namearg = callfunc.args[1] |
| self.assertIsInstance(namearg, nodes.Name) |
| self.assertEqual(namearg.fromlineno, 5) |
| self.assertEqual(namearg.tolineno, 5) |
| # on line 10: |
| # fonction(1, |
| # 2, |
| # 3, |
| # 4) |
| discard = stmts[2] |
| self.assertIsInstance(discard, nodes.Expr) |
| self.assertEqual(discard.fromlineno, 10) |
| self.assertEqual(discard.tolineno, 13) |
| callfunc = discard.value |
| self.assertIsInstance(callfunc, nodes.Call) |
| self.assertEqual(callfunc.fromlineno, 10) |
| self.assertEqual(callfunc.tolineno, 13) |
| name = callfunc.func |
| self.assertIsInstance(name, nodes.Name) |
| self.assertEqual(name.fromlineno, 10) |
| self.assertEqual(name.tolineno, 10) |
| for i, arg in enumerate(callfunc.args): |
| self.assertIsInstance(arg, nodes.Const) |
| self.assertEqual(arg.fromlineno, 10+i) |
| self.assertEqual(arg.tolineno, 10+i) |
| |
| def test_function_lineno(self): |
| stmts = self.astroid.body |
| # on line 15: |
| # def definition(a, |
| # b, |
| # c): |
| # return a + b + c |
| function = stmts[3] |
| self.assertIsInstance(function, nodes.FunctionDef) |
| self.assertEqual(function.fromlineno, 15) |
| self.assertEqual(function.tolineno, 18) |
| return_ = function.body[0] |
| self.assertIsInstance(return_, nodes.Return) |
| self.assertEqual(return_.fromlineno, 18) |
| self.assertEqual(return_.tolineno, 18) |
| if sys.version_info < (3, 0): |
| self.assertEqual(function.blockstart_tolineno, 17) |
| else: |
| self.skipTest('FIXME http://bugs.python.org/issue10445 ' |
| '(no line number on function args)') |
| |
| def test_decorated_function_lineno(self): |
| astroid = builder.parse(''' |
| @decorator |
| def function( |
| arg): |
| print (arg) |
| ''', __name__) |
| function = astroid['function'] |
| self.assertEqual(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now |
| 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_class_lineno(self): |
| stmts = self.astroid.body |
| # on line 20: |
| # class debile(dict, |
| # object): |
| # pass |
| class_ = stmts[4] |
| self.assertIsInstance(class_, nodes.ClassDef) |
| self.assertEqual(class_.fromlineno, 20) |
| self.assertEqual(class_.tolineno, 22) |
| self.assertEqual(class_.blockstart_tolineno, 21) |
| pass_ = class_.body[0] |
| self.assertIsInstance(pass_, nodes.Pass) |
| self.assertEqual(pass_.fromlineno, 22) |
| self.assertEqual(pass_.tolineno, 22) |
| |
| def test_if_lineno(self): |
| stmts = self.astroid.body |
| # on line 20: |
| # if aaaa: pass |
| # else: |
| # aaaa,bbbb = 1,2 |
| # aaaa,bbbb = bbbb,aaaa |
| if_ = stmts[5] |
| self.assertIsInstance(if_, nodes.If) |
| self.assertEqual(if_.fromlineno, 24) |
| self.assertEqual(if_.tolineno, 27) |
| self.assertEqual(if_.blockstart_tolineno, 24) |
| self.assertEqual(if_.orelse[0].fromlineno, 26) |
| self.assertEqual(if_.orelse[1].tolineno, 27) |
| |
| def test_for_while_lineno(self): |
| for code in (''' |
| for a in range(4): |
| print (a) |
| break |
| else: |
| print ("bouh") |
| ''', ''' |
| while a: |
| print (a) |
| break |
| else: |
| print ("bouh") |
| '''): |
| astroid = builder.parse(code, __name__) |
| stmt = astroid.body[0] |
| self.assertEqual(stmt.fromlineno, 2) |
| self.assertEqual(stmt.tolineno, 6) |
| self.assertEqual(stmt.blockstart_tolineno, 2) |
| self.assertEqual(stmt.orelse[0].fromlineno, 6) # XXX |
| self.assertEqual(stmt.orelse[0].tolineno, 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_try_finally_lineno(self): |
| astroid = builder.parse(''' |
| try: |
| print (a) |
| finally: |
| print ("bouh") |
| ''', __name__) |
| try_ = astroid.body[0] |
| self.assertEqual(try_.fromlineno, 2) |
| self.assertEqual(try_.tolineno, 5) |
| self.assertEqual(try_.blockstart_tolineno, 2) |
| self.assertEqual(try_.finalbody[0].fromlineno, 5) # XXX |
| self.assertEqual(try_.finalbody[0].tolineno, 5) |
| |
| |
| 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_with_lineno(self): |
| astroid = builder.parse(''' |
| from __future__ import with_statement |
| with file("/tmp/pouet") as f: |
| print (f) |
| ''', __name__) |
| with_ = astroid.body[1] |
| self.assertEqual(with_.fromlineno, 3) |
| self.assertEqual(with_.tolineno, 4) |
| self.assertEqual(with_.blockstart_tolineno, 3) |
| |
| |
| class BuilderTest(unittest.TestCase): |
| |
| def setUp(self): |
| self.builder = builder.AstroidBuilder() |
| |
| def test_data_build_null_bytes(self): |
| with self.assertRaises(exceptions.AstroidSyntaxError): |
| self.builder.string_build('\x00') |
| |
| def test_data_build_invalid_x_escape(self): |
| with self.assertRaises(exceptions.AstroidSyntaxError): |
| self.builder.string_build('"\\x1"') |
| |
| def test_missing_file(self): |
| with self.assertRaises(exceptions.AstroidBuildingError): |
| resources.build_file('data/inexistant.py') |
| |
| def test_inspect_build0(self): |
| """test astroid tree build from a living object""" |
| builtin_ast = MANAGER.ast_from_module_name(BUILTINS) |
| if six.PY2: |
| fclass = builtin_ast['file'] |
| self.assertIn('name', fclass) |
| self.assertIn('mode', fclass) |
| self.assertIn('read', fclass) |
| self.assertTrue(fclass.newstyle) |
| self.assertTrue(fclass.pytype(), '%s.type' % BUILTINS) |
| self.assertIsInstance(fclass['read'], nodes.FunctionDef) |
| # check builtin function has args.args == None |
| dclass = builtin_ast['dict'] |
| self.assertIsInstance(dclass['has_key'].args, nodes.Unknown) |
| # just check type and object are there |
| builtin_ast.getattr('type') |
| objectastroid = builtin_ast.getattr('object')[0] |
| self.assertIsInstance(objectastroid.getattr('__new__')[0], nodes.FunctionDef) |
| # check open file alias |
| builtin_ast.getattr('open') |
| # check 'help' is there (defined dynamically by site.py) |
| builtin_ast.getattr('help') |
| # check property has __init__ |
| pclass = builtin_ast['property'] |
| self.assertIn('__init__', pclass) |
| self.assertIsInstance(builtin_ast['None'], nodes.NameConstant) |
| self.assertIsInstance(builtin_ast['True'], nodes.NameConstant) |
| self.assertIsInstance(builtin_ast['False'], nodes.NameConstant) |
| self.assertIsInstance(builtin_ast['NotImplemented'], nodes.NameConstant) |
| self.assertIsInstance(builtin_ast['Ellipsis'], nodes.Ellipsis) |
| if six.PY3: |
| self.assertIsInstance(builtin_ast['Exception'], nodes.ClassDef) |
| self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ClassDef) |
| else: |
| self.assertIsInstance(builtin_ast['Exception'], nodes.ImportFrom) |
| self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ImportFrom) |
| |
| def test_inspect_build1(self): |
| time_ast = MANAGER.ast_from_module_name('time') |
| self.assertTrue(time_ast) |
| self.assertIsInstance(time_ast['time'].args, nodes.Unknown) |
| |
| if os.name == 'java': |
| test_inspect_build1 = unittest.expectedFailure(test_inspect_build1) |
| |
| def test_inspect_build2(self): |
| """test astroid tree build from a living object""" |
| try: |
| from mx import DateTime |
| except ImportError: |
| self.skipTest('test skipped: mxDateTime is not available') |
| else: |
| dt_ast = raw_building.ast_from_object(DateTime) # self.builder.inspect_build(DateTime) |
| dt_ast.getattr('DateTime') |
| # this one is failing since DateTimeType.__module__ = 'builtins' ! |
| #dt_ast.getattr('DateTimeType') |
| |
| def test_inspect_build3(self): |
| # self.builder.inspect_build(unittest) |
| raw_building.ast_from_object(unittest) |
| |
| @test_utils.require_version(maxver='3.0') |
| def test_inspect_build_instance(self): |
| """test astroid tree build from a living object""" |
| import exceptions |
| exceptions_ast = raw_building.ast_from_object(exceptions) |
| environment_error = exceptions_ast['EnvironmentError'] |
| # things like EnvironmentError.strerror are now (2.5) data |
| # descriptors on the class instead of entries in the __dict__ |
| # of an instance |
| self.assertIn('errno', environment_error) |
| self.assertIn('strerror', environment_error) |
| self.assertIn('filename', environment_error) |
| |
| def test_inspect_build_type_object(self): |
| builtin_ast = MANAGER.ast_from_module_name(BUILTINS) |
| |
| inferred = list(builtin_ast.igetattr('object')) |
| self.assertEqual(len(inferred), 1) |
| inferred = inferred[0] |
| self.assertEqual(inferred.name, 'object') |
| inferred.as_string() # no crash test |
| |
| inferred = list(builtin_ast.igetattr('type')) |
| self.assertEqual(len(inferred), 1) |
| inferred = inferred[0] |
| self.assertEqual(inferred.name, 'type') |
| inferred.as_string() # no crash test |
| |
| def test_inspect_transform_module(self): |
| # ensure no cached version of the time module |
| MANAGER._mod_file_cache.pop(('time', None), None) |
| MANAGER.astroid_cache.pop('time', None) |
| def transform_time(node): |
| if node.name == 'time': |
| node.transformed = True |
| MANAGER.register_transform(nodes.Module, transform_time) |
| try: |
| time_ast = MANAGER.ast_from_module_name('time') |
| self.assertTrue(getattr(time_ast, 'transformed', False)) |
| finally: |
| MANAGER.unregister_transform(nodes.Module, transform_time) |
| |
| def test_package_name(self): |
| """test base properties and method of a astroid module""" |
| datap = resources.build_file('data/__init__.py', 'data') |
| self.assertEqual(datap.name, 'data') |
| self.assertEqual(datap.package, 1) |
| datap = resources.build_file('data/__init__.py', 'data.__init__') |
| self.assertEqual(datap.name, 'data') |
| self.assertEqual(datap.package, 1) |
| |
| def test_yield_parent(self): |
| """check if we added discard nodes as yield parent (w/ compiler)""" |
| code = """ |
| def yiell(): #@ |
| yield 0 |
| if noe: |
| yield more |
| """ |
| func = builder.extract_node(code) |
| self.assertIsInstance(func, nodes.FunctionDef) |
| stmt = func.body[0] |
| self.assertIsInstance(stmt, nodes.Expr) |
| self.assertIsInstance(stmt.value, nodes.Yield) |
| self.assertIsInstance(func.body[1].body[0], nodes.Expr) |
| self.assertIsInstance(func.body[1].body[0].value, nodes.Yield) |
| |
| def test_object(self): |
| obj_ast = raw_building.ast_from_object(object) # self.builder.inspect_build(object) |
| self.assertIn('__setattr__', obj_ast) |
| |
| 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) |
| |
| @unittest.expectedFailure |
| 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')) |
| |
| @unittest.skipIf(util.JYTHON, |
| 'This test is skipped on Jython, because the ' |
| 'socket object is patched later on with the ' |
| 'methods we are looking for. Since we do not ' |
| 'understand setattr in for loops yet, we skip this') |
| def test_socket_build(self): |
| import socket |
| astroid = self.builder.module_build(socket) |
| # XXX just check the first one. Actually 3 objects are inferred (look at |
| # the socket module) but the last one as those attributes dynamically |
| # set and astroid is missing this. |
| for fclass in astroid.igetattr('socket'): |
| self.assertIn('connect', fclass) |
| self.assertIn('send', fclass) |
| self.assertIn('close', fclass) |
| break |
| |
| 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_no_future_imports(self): |
| mod = builder.parse("import sys") |
| self.assertEqual(set(), mod.future_imports) |
| |
| def test_future_imports(self): |
| mod = builder.parse("from __future__ import print_function") |
| self.assertEqual(frozenset(['print_function']), mod.future_imports) |
| |
| def test_two_future_imports(self): |
| mod = builder.parse(""" |
| from __future__ import print_function |
| from __future__ import absolute_import |
| """) |
| self.assertEqual(frozenset(['print_function', 'absolute_import']), mod.future_imports) |
| |
| def test_inferred_build(self): |
| code = ''' |
| class A: pass |
| A.type = "class" |
| |
| def A_assign_type(self): |
| print (self) |
| A.assign_type = A_assign_type |
| ''' |
| astroid = builder.parse(code) |
| lclass = list(astroid.igetattr('A')) |
| self.assertEqual(len(lclass), 1) |
| lclass = lclass[0] |
| self.assertIn('assign_type', lclass.external_attrs) |
| self.assertIn('type', lclass.external_attrs) |
| |
| def test_augassign_attr(self): |
| builder.parse(""" |
| class Counter: |
| v = 0 |
| def inc(self): |
| self.v += 1 |
| """, __name__) |
| # TODO: Check self.v += 1 generate AugAssign(AssAttr(...)), |
| # not AugAssign(GetAttr(AssName...)) |
| |
| def test_inferred_dont_pollute(self): |
| code = ''' |
| def func(a=None): |
| a.custom_attr = 0 |
| a #@ |
| def func2(a={}): |
| a.custom_attr = 0 |
| a #@ |
| ''' |
| name_nodes = builder.extract_node(code) |
| for node in name_nodes: |
| self.assertNotIn('custom_attr', next(node.infer()).locals) |
| self.assertNotIn('custom_attr', next(node.infer()).instance_attrs) |
| |
| 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_build_constants(self): |
| '''test expected values of constants after rebuilding''' |
| code = ''' |
| def func(): |
| return None |
| return |
| return 'None' |
| ''' |
| astroid = builder.parse(code) |
| none, nothing, chain = [ret.value for ret in astroid.body[0].body] |
| self.assertIsInstance(none, nodes.Const) |
| self.assertIsNone(none.value) |
| self.assertIsNone(nothing) |
| self.assertIsInstance(chain, nodes.Const) |
| self.assertEqual(chain.value, 'None') |
| |
| def test_not_implemented(self): |
| node = builder.extract_node(''' |
| NotImplemented #@ |
| ''') |
| inferred = next(node.infer()) |
| self.assertIsInstance(inferred, nodes.Const) |
| self.assertEqual(inferred.value, NotImplemented) |
| |
| |
| class FileBuildTest(unittest.TestCase): |
| def setUp(self): |
| self.module = resources.build_file('data/module.py', 'data.module') |
| |
| def test_module_base_props(self): |
| """test base properties and method of a astroid module""" |
| module = self.module |
| self.assertEqual(module.name, 'data.module') |
| self.assertEqual(module.doc, "test module for astroid\n") |
| self.assertEqual(module.fromlineno, 0) |
| self.assertIsNone(module.parent) |
| self.assertEqual(module.frame(), module) |
| self.assertEqual(module.root(), module) |
| self.assertEqual(module.source_file, os.path.abspath(resources.find('data/module.py'))) |
| self.assertEqual(module.pure_python, 1) |
| self.assertEqual(module.package, 0) |
| self.assertFalse(module.is_statement) |
| self.assertEqual(module.statement(), module) |
| self.assertEqual(module.statement(), module) |
| |
| def test_module_locals(self): |
| """test the 'locals' dictionary of a astroid module""" |
| module = self.module |
| _locals = module.locals |
| self.assertEqual(_locals, module.globals) |
| keys = sorted(_locals.keys()) |
| should = ['MY_DICT', 'NameNode', 'YO', 'YOUPI', |
| '__revision__', 'global_access', 'modutils', 'four_args', |
| 'os', 'redirect'] |
| should.sort() |
| self.assertEqual(keys, sorted(should)) |
| |
| def test_function_base_props(self): |
| """test base properties and method of a astroid function""" |
| module = self.module |
| function = module['global_access'] |
| self.assertEqual(function.name, 'global_access') |
| self.assertEqual(function.doc, 'function test') |
| self.assertEqual(function.fromlineno, 11) |
| self.assertTrue(function.parent) |
| self.assertEqual(function.frame(), function) |
| self.assertEqual(function.parent.frame(), module) |
| self.assertEqual(function.root(), module) |
| self.assertEqual([n.name for n in function.args.args], ['key', 'val']) |
| self.assertEqual(function.type, 'function') |
| |
| def test_function_locals(self): |
| """test the 'locals' dictionary of a astroid function""" |
| _locals = self.module['global_access'].locals |
| self.assertEqual(len(_locals), 4) |
| keys = sorted(_locals.keys()) |
| self.assertEqual(keys, ['i', 'key', 'local', 'val']) |
| |
| def test_class_base_props(self): |
| """test base properties and method of a astroid class""" |
| module = self.module |
| klass = module['YO'] |
| self.assertEqual(klass.name, 'YO') |
| self.assertEqual(klass.doc, 'hehe') |
| self.assertEqual(klass.fromlineno, 25) |
| self.assertTrue(klass.parent) |
| self.assertEqual(klass.frame(), klass) |
| self.assertEqual(klass.parent.frame(), module) |
| self.assertEqual(klass.root(), module) |
| self.assertEqual(klass.basenames, []) |
| if six.PY3: |
| self.assertTrue(klass.newstyle) |
| else: |
| self.assertFalse(klass.newstyle) |
| |
| def test_class_locals(self): |
| """test the 'locals' dictionary of a astroid class""" |
| module = self.module |
| klass1 = module['YO'] |
| locals1 = klass1.locals |
| keys = sorted(locals1.keys()) |
| self.assertEqual(keys, ['__init__', 'a']) |
| klass2 = module['YOUPI'] |
| locals2 = klass2.locals |
| keys = locals2.keys() |
| self.assertEqual(sorted(keys), |
| ['__init__', 'class_attr', 'class_method', |
| 'method', 'static_method']) |
| |
| def test_class_instance_attrs(self): |
| module = self.module |
| klass1 = module['YO'] |
| klass2 = module['YOUPI'] |
| self.assertEqual(list(klass1.instance_attrs.keys()), ['yo']) |
| self.assertEqual(list(klass2.instance_attrs.keys()), ['member']) |
| |
| def test_class_basenames(self): |
| module = self.module |
| klass1 = module['YO'] |
| klass2 = module['YOUPI'] |
| self.assertEqual(klass1.basenames, []) |
| self.assertEqual(klass2.basenames, ['YO']) |
| |
| def test_method_base_props(self): |
| """test base properties and method of a astroid method""" |
| klass2 = self.module['YOUPI'] |
| # "normal" method |
| method = klass2['method'] |
| self.assertEqual(method.name, 'method') |
| self.assertEqual([n.name for n in method.args.args], ['self']) |
| self.assertEqual(method.doc, 'method test') |
| self.assertEqual(method.fromlineno, 47) |
| self.assertEqual(method.type, 'method') |
| # class method |
| method = klass2['class_method'] |
| self.assertEqual([n.name for n in method.args.args], ['cls']) |
| self.assertEqual(method.type, 'classmethod') |
| # static method |
| method = klass2['static_method'] |
| self.assertEqual(method.args.args, []) |
| self.assertEqual(method.type, 'staticmethod') |
| |
| def test_method_locals(self): |
| """test the 'locals' dictionary of a astroid method""" |
| method = self.module['YOUPI']['method'] |
| _locals = method.locals |
| keys = sorted(_locals) |
| if sys.version_info < (3, 0): |
| self.assertEqual(len(_locals), 6) |
| self.assertEqual(keys, ['MY_DICT', 'a', 'autre', 'b', 'local', 'self']) |
| else:# ListComp variables are no more accessible outside |
| self.assertEqual(len(_locals), 4) |
| self.assertEqual(keys, ['MY_DICT', 'autre', 'local', 'self']) |
| |
| def test_unknown_encoding(self): |
| with self.assertRaises(exceptions.AstroidSyntaxError): |
| with resources.tempfile_with_content(b'# -*- coding: lala -*-') as tmp: |
| builder.AstroidBuilder().file_build(tmp) |
| |
| |
| class ModuleBuildTest(resources.SysPathSetup, FileBuildTest): |
| |
| def setUp(self): |
| super(ModuleBuildTest, self).setUp() |
| abuilder = builder.AstroidBuilder() |
| try: |
| import data.module |
| except ImportError: |
| # Make pylint happy. |
| self.skipTest('Unable to load data.module') |
| else: |
| self.module = abuilder.module_build(data.module, 'data.module') |
| |
| @unittest.skipIf(six.PY3, "guess_encoding not used on Python 3") |
| class TestGuessEncoding(unittest.TestCase): |
| def setUp(self): |
| self.guess_encoding = builder._guess_encoding |
| |
| def testEmacs(self): |
| e = self.guess_encoding('# -*- coding: UTF-8 -*-') |
| self.assertEqual(e, 'UTF-8') |
| e = self.guess_encoding('# -*- coding:UTF-8 -*-') |
| self.assertEqual(e, 'UTF-8') |
| e = self.guess_encoding(''' |
| ### -*- coding: ISO-8859-1 -*- |
| ''') |
| self.assertEqual(e, 'ISO-8859-1') |
| e = self.guess_encoding(''' |
| |
| ### -*- coding: ISO-8859-1 -*- |
| ''') |
| self.assertIsNone(e) |
| |
| def testVim(self): |
| e = self.guess_encoding('# vim:fileencoding=UTF-8') |
| self.assertEqual(e, 'UTF-8') |
| e = self.guess_encoding(''' |
| ### vim:fileencoding=ISO-8859-1 |
| ''') |
| self.assertEqual(e, 'ISO-8859-1') |
| e = self.guess_encoding(''' |
| |
| ### vim:fileencoding= ISO-8859-1 |
| ''') |
| self.assertIsNone(e) |
| |
| def test_wrong_coding(self): |
| # setting "coding" varaible |
| e = self.guess_encoding("coding = UTF-8") |
| self.assertIsNone(e) |
| # setting a dictionnary entry |
| e = self.guess_encoding("coding:UTF-8") |
| self.assertIsNone(e) |
| # setting an arguement |
| e = self.guess_encoding("def do_something(a_word_with_coding=None):") |
| self.assertIsNone(e) |
| |
| def testUTF8(self): |
| e = self.guess_encoding('\xef\xbb\xbf any UTF-8 data') |
| self.assertEqual(e, 'UTF-8') |
| e = self.guess_encoding(' any UTF-8 data \xef\xbb\xbf') |
| self.assertIsNone(e) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |