| Index: third_party/pylint/testutils.py
|
| diff --git a/third_party/pylint/testutils.py b/third_party/pylint/testutils.py
|
| index 1dd083fe78eec50527c9a2cf31102ebfa36cfbdc..2f9af4d102a9f7aebce6a86d7f2afd510393650f 100644
|
| --- a/third_party/pylint/testutils.py
|
| +++ b/third_party/pylint/testutils.py
|
| @@ -14,20 +14,23 @@
|
| # this program; if not, write to the Free Software Foundation, Inc.,
|
| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
| """functional/non regression tests for pylint"""
|
| -from __future__ import with_statement
|
| +from __future__ import print_function
|
|
|
| import collections
|
| import contextlib
|
| import functools
|
| +import os
|
| import sys
|
| import re
|
| +import unittest
|
| +import tempfile
|
| +import tokenize
|
|
|
| from glob import glob
|
| -from os import linesep
|
| +from os import linesep, getcwd, sep
|
| from os.path import abspath, basename, dirname, isdir, join, splitext
|
| -from cStringIO import StringIO
|
|
|
| -from logilab.common import testlib
|
| +from astroid import test_utils
|
|
|
| from pylint import checkers
|
| from pylint.utils import PyLintASTWalker
|
| @@ -35,6 +38,9 @@ from pylint.reporters import BaseReporter
|
| from pylint.interfaces import IReporter
|
| from pylint.lint import PyLinter
|
|
|
| +import six
|
| +from six.moves import StringIO
|
| +
|
|
|
| # Utils
|
|
|
| @@ -89,9 +95,11 @@ class TestReporter(BaseReporter):
|
|
|
| __implements____ = IReporter
|
|
|
| - def __init__(self):
|
| + def __init__(self): # pylint: disable=super-init-not-called
|
| +
|
| self.message_ids = {}
|
| self.reset()
|
| + self.path_strip_prefix = getcwd() + sep
|
|
|
| def reset(self):
|
| self.out = StringIO()
|
| @@ -113,7 +121,7 @@ class TestReporter(BaseReporter):
|
| def finalize(self):
|
| self.messages.sort()
|
| for msg in self.messages:
|
| - print >> self.out, msg
|
| + print(msg, file=self.out)
|
| result = self.out.getvalue()
|
| self.reset()
|
| return result
|
| @@ -122,34 +130,15 @@ class TestReporter(BaseReporter):
|
| """ignore layouts"""
|
|
|
|
|
| -if sys.version_info < (2, 6):
|
| - class Message(tuple):
|
| - def __new__(cls, msg_id, line=None, node=None, args=None):
|
| - return tuple.__new__(cls, (msg_id, line, node, args))
|
| -
|
| - @property
|
| - def msg_id(self):
|
| - return self[0]
|
| - @property
|
| - def line(self):
|
| - return self[1]
|
| - @property
|
| - def node(self):
|
| - return self[2]
|
| - @property
|
| - def args(self):
|
| - return self[3]
|
| -
|
| -
|
| -else:
|
| - class Message(collections.namedtuple('Message',
|
| - ['msg_id', 'line', 'node', 'args'])):
|
| - def __new__(cls, msg_id, line=None, node=None, args=None):
|
| - return tuple.__new__(cls, (msg_id, line, node, args))
|
| +class Message(collections.namedtuple('Message',
|
| + ['msg_id', 'line', 'node', 'args'])):
|
| + def __new__(cls, msg_id, line=None, node=None, args=None):
|
| + return tuple.__new__(cls, (msg_id, line, node, args))
|
|
|
|
|
| class UnittestLinter(object):
|
| """A fake linter class to capture checker messages."""
|
| + # pylint: disable=unused-argument, no-self-use
|
|
|
| def __init__(self):
|
| self._messages = []
|
| @@ -161,14 +150,15 @@ class UnittestLinter(object):
|
| finally:
|
| self._messages = []
|
|
|
| - def add_message(self, msg_id, line=None, node=None, args=None):
|
| + def add_message(self, msg_id, line=None, node=None, args=None,
|
| + confidence=None):
|
| self._messages.append(Message(msg_id, line, node, args))
|
|
|
| def is_message_enabled(self, *unused_args):
|
| return True
|
|
|
| def add_stats(self, **kwargs):
|
| - for name, value in kwargs.iteritems():
|
| + for name, value in six.iteritems(kwargs):
|
| self.stats[name] = value
|
| return self.stats
|
|
|
| @@ -181,7 +171,7 @@ def set_config(**kwargs):
|
| def _Wrapper(fun):
|
| @functools.wraps(fun)
|
| def _Forward(self):
|
| - for key, value in kwargs.iteritems():
|
| + for key, value in six.iteritems(kwargs):
|
| setattr(self.checker.config, key, value)
|
| if isinstance(self, CheckerTestCase):
|
| # reopen checker in case, it may be interested in configuration change
|
| @@ -192,7 +182,7 @@ def set_config(**kwargs):
|
| return _Wrapper
|
|
|
|
|
| -class CheckerTestCase(testlib.TestCase):
|
| +class CheckerTestCase(unittest.TestCase):
|
| """A base testcase class for unittesting individual checker classes."""
|
| CHECKER_CLASS = None
|
| CONFIG = {}
|
| @@ -200,7 +190,7 @@ class CheckerTestCase(testlib.TestCase):
|
| def setUp(self):
|
| self.linter = UnittestLinter()
|
| self.checker = self.CHECKER_CLASS(self.linter) # pylint: disable=not-callable
|
| - for key, value in self.CONFIG.iteritems():
|
| + for key, value in six.iteritems(self.CONFIG):
|
| setattr(self.checker.config, key, value)
|
| self.checker.open()
|
|
|
| @@ -250,13 +240,13 @@ else:
|
|
|
| INFO_TEST_RGX = re.compile(r'^func_i\d\d\d\d$')
|
|
|
| -def exception_str(self, ex):
|
| +def exception_str(self, ex): # pylint: disable=unused-argument
|
| """function used to replace default __str__ method of exception instances"""
|
| return 'in %s\n:: %s' % (ex.file, ', '.join(ex.args))
|
|
|
| # Test classes
|
|
|
| -class LintTestUsingModule(testlib.TestCase):
|
| +class LintTestUsingModule(unittest.TestCase):
|
| INPUT_DIR = None
|
| DEFAULT_PACKAGE = 'input'
|
| package = DEFAULT_PACKAGE
|
| @@ -265,6 +255,7 @@ class LintTestUsingModule(testlib.TestCase):
|
| depends = None
|
| output = None
|
| _TEST_TYPE = 'module'
|
| + maxDiff = None
|
|
|
| def shortDescription(self):
|
| values = {'mode' : self._TEST_TYPE,
|
| @@ -296,11 +287,11 @@ class LintTestUsingModule(testlib.TestCase):
|
| self.linter.disable('I')
|
| try:
|
| self.linter.check(tocheck)
|
| - except Exception, ex:
|
| + except Exception as ex:
|
| # need finalization to restore a correct state
|
| self.linter.reporter.finalize()
|
| ex.file = tocheck
|
| - print ex
|
| + print(ex)
|
| ex.__str__ = exception_str
|
| raise
|
| self._check_result(self.linter.reporter.finalize())
|
| @@ -347,11 +338,11 @@ class LintTestUpdate(LintTestUsingModule):
|
|
|
| def cb_test_gen(base_class):
|
| def call(input_dir, msg_dir, module_file, messages_file, dependencies):
|
| + # pylint: disable=no-init
|
| class LintTC(base_class):
|
| module = module_file.replace('.py', '')
|
| output = messages_file
|
| depends = dependencies or None
|
| - tags = testlib.Tags(('generated', 'pylint_input_%s' % module))
|
| INPUT_DIR = input_dir
|
| MSG_DIR = msg_dir
|
| return LintTC
|
| @@ -372,7 +363,7 @@ def make_tests(input_dir, msg_dir, filter_rgx, callbacks):
|
| for module_file, messages_file in (
|
| get_tests_info(input_dir, msg_dir, 'func_', '')
|
| ):
|
| - if not is_to_run(module_file):
|
| + if not is_to_run(module_file) or module_file.endswith('.pyc'):
|
| continue
|
| base = module_file.replace('func_', '').replace('.py', '')
|
|
|
| @@ -384,3 +375,38 @@ def make_tests(input_dir, msg_dir, filter_rgx, callbacks):
|
| if test:
|
| tests.append(test)
|
| return tests
|
| +
|
| +def tokenize_str(code):
|
| + return list(tokenize.generate_tokens(StringIO(code).readline))
|
| +
|
| +@contextlib.contextmanager
|
| +def create_tempfile(content=None):
|
| + """Create a new temporary file.
|
| +
|
| + If *content* parameter is given, then it will be written
|
| + in the temporary file, before passing it back.
|
| + This is a context manager and should be used with a *with* statement.
|
| + """
|
| + # Can't use tempfile.NamedTemporaryFile here
|
| + # because on Windows the file must be closed before writing to it,
|
| + # see http://bugs.python.org/issue14243
|
| + fd, tmp = tempfile.mkstemp()
|
| + if content:
|
| + if sys.version_info >= (3, 0):
|
| + # erff
|
| + os.write(fd, bytes(content, 'ascii'))
|
| + else:
|
| + os.write(fd, content)
|
| + try:
|
| + yield tmp
|
| + finally:
|
| + os.close(fd)
|
| + os.remove(tmp)
|
| +
|
| +@contextlib.contextmanager
|
| +def create_file_backed_module(code):
|
| + """Create an astroid module for the given code, backed by a real file."""
|
| + with create_tempfile() as temp:
|
| + module = test_utils.build_module(code)
|
| + module.file = temp
|
| + yield module
|
|
|