Beispiel #1
0
def linter():
    linter = PyLinter()
    linter.set_reporter(MinimalTestReporter())
    checkers.initialize(linter)
    linter.register_checker(OverlappingExceptionsChecker(linter))
    linter.disable('I')
    return linter
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        # self.linter.set_reporter(TextReporter())
        expected = ( '************* Module 0123\n'
                     'C0301:001\n'
                     'C0301:002\n'
                     )

        output = StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(output.getvalue(), expected)
Beispiel #3
0
def linter():
    linter = PyLinter()
    linter.set_reporter(MinimalTestReporter())
    checkers.initialize(linter)
    linter.register_checker(MultipleTypesChecker(linter))
    linter.disable('I')
    return linter
Beispiel #4
0
def linter():
    linter = PyLinter()
    linter.set_reporter(MinimalTestReporter())
    checkers.initialize(linter)
    linter.register_checker(BadBuiltinChecker(linter))
    linter.disable('I')
    return linter
Beispiel #5
0
def linter():
    linter = PyLinter()
    linter.disable('I')
    linter.config.persistent = 0
    # register checkers
    checkers.initialize(linter)
    linter.set_reporter(testutils.TestReporter())
    return linter
Beispiel #6
0
def linter():
    linter = PyLinter(reporter=TextReporter())
    linter.disable('I')
    linter.config.persistent = 0
    # register checkers
    checkers.initialize(linter)
    os.environ.pop('PYLINTRC', None)
    return linter
Beispiel #7
0
def linter():
    linter = PyLinter()
    linter.set_reporter(MinimalTestReporter())
    checkers.initialize(linter)
    register(linter)
    linter.disable('all')
    linter.enable('too-complex')
    return linter
Beispiel #8
0
def linter():
    linter = PyLinter()
    linter.disable('I')
    linter.config.persistent = 0
    # register checkers
    checkers.initialize(linter)
    linter.set_reporter(testutils.TestReporter())
    return linter
Beispiel #9
0
def linter():
    linter = PyLinter()
    linter.set_reporter(MinimalTestReporter())
    checkers.initialize(linter)
    register(linter)
    linter.disable('all')
    linter.enable('too-complex')
    return linter
Beispiel #10
0
    def __init__(self, options: Optional[dict] = None):
        options = options or {}
        checker = PyLinter(reporter=CollectingReporter())
        checkers.initialize(checker)
        checker.disable("I")  # suppress info messages
        for k, v in options.items():
            checker.global_set_option(k, v)

        self._inner = checker
Beispiel #11
0
def linter():
    linter = PyLinter()
    linter.set_reporter(InMemReporter())
    checkers.initialize(linter)
    register(linter)
    linter.disable('all')
    linter.enable(SentryStackChecker.ADD_EXC_INFO)
    linter.enable(SentryStackChecker.CHANGE_TO_EXC_INFO)
    return linter
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  'C0301:001\n'
                                  'C0301:002\n')

    def test_parseable_output_deprecated(self):
        with warnings.catch_warnings(record=True) as cm:
            warnings.simplefilter("always")
            ParseableTextReporter()
        
        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)

    def test_parseable_output_regression(self):
        output = six.StringIO()
        with warnings.catch_warnings(record=True):
            linter = PyLinter(reporter=ParseableTextReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  '0123:1: [C0301(line-too-long), ] '
                                  'Line too long (1/2)\n')

    def test_display_results_is_renamed(self):
        class CustomReporter(TextReporter):
            def _display(self, layout):
                return None

        reporter = CustomReporter()
        with self.assertRaises(AttributeError):
            reporter.display_results
Beispiel #13
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            'C0301:001\n'
            'C0301:002\n')

    def test_parseable_output_deprecated(self):
        with warnings.catch_warnings(record=True) as cm:
            warnings.simplefilter("always")
            ParseableTextReporter()

        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)

    def test_parseable_output_regression(self):
        output = six.StringIO()
        with warnings.catch_warnings(record=True):
            linter = PyLinter(reporter=ParseableTextReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            '0123:1: [C0301(line-too-long), ] '
            'Line too long (1/2)\n')

    def test_display_results_is_renamed(self):
        class CustomReporter(TextReporter):
            def _display(self, layout):
                return None

        reporter = CustomReporter()
        with self.assertRaises(AttributeError):
            reporter.display_results
Beispiel #14
0
def py3(check):
    """Verify if a custom check or integration can run on python 3. CHECK
    can be an integration name or a valid path to a Python module or package folder.
    """

    root = get_root()
    if check == 'datadog_checks_base':
        path_to_module = os.path.join(root, check, 'datadog_checks', 'base')
    elif check in get_valid_checks() and check not in NOT_CHECKS:
        path_to_module = os.path.join(root, check, 'datadog_checks', check)
    else:
        path_to_module = check

    if not os.path.exists(path_to_module):
        abort("{} does not exist.".format(path_to_module))

    echo_info("Validating python3 compatibility of {}...".format(check))
    with closing(StringIO()) as out:
        linter = PyLinter(reporter=JSONReporter(output=out))
        linter.load_default_plugins()
        linter.python3_porting_mode()
        # Disable `no-absolute-import`, which checks for a behaviour that's already part of python 2.7
        # cf https://www.python.org/dev/peps/pep-0328/
        linter.disable("no-absolute-import")
        with fix_import_path([path_to_module]):
            linter.check(path_to_module)
            linter.generate_reports()
        results = json.loads(out.getvalue() or "{}")

    if results:
        echo_failure("Incompatibilities were found for {}:".format(check))
        current_path = None
        for problem in sorted(results, key=itemgetter("path")):
            # An issue found by pylint is a dict like
            # {
            #     "message": "Calling a dict.iter*() method",
            #     "obj": "OpenFilesCheck.check",
            #     "column": 27,
            #     "path": "/path/to/file.py",
            #     "line": 235,
            #     "message-id": "W1620",
            #     "type": "warning",
            #     "symbol": "dict-iter-method",
            #     "module": "file"
            # }
            path = problem["path"]
            if current_path is None or path != current_path:
                echo_info("File {}:".format(path))
            echo_failure("  Line {}, column {}: {}".format(
                problem["line"], problem["column"], problem["message"]))
            current_path = path
        abort()
    else:
        echo_success("{} is compatible with python3".format(check))
Beispiel #15
0
 def linter(register, enable, disable):
     _linter = PyLinter()
     _linter.set_reporter(MinimalTestReporter())
     checkers.initialize(_linter)
     if register:
         register(_linter)
     if disable:
         for msg in disable:
             _linter.disable(msg)
     if enable:
         for msg in enable:
             _linter.enable(msg)
     return _linter
Beispiel #16
0
def run_linter(files=None):
    if files is None:
        return
    logger.info('Linting {}'.format(', '.join(files)))
    rep = ColorizedTextReporter()
    linter = PyLinter(reporter=rep, pylintrc=find_pylintrc())
    linter.load_default_plugins()
    linter.disable('I')
    linter.enable('c-extension-no-member')
    linter.read_config_file()
    linter.load_config_file()
    linter.check(files)
    linter.generate_reports()
Beispiel #17
0
def linter(checker, register, enable, disable, reporter):
    _linter = PyLinter()
    _linter.set_reporter(reporter())
    checkers.initialize(_linter)
    if register:
        register(_linter)
    if checker:
        _linter.register_checker(checker(_linter))
    if disable:
        for msg in disable:
            _linter.disable(msg)
    if enable:
        for msg in enable:
            _linter.enable(msg)
    os.environ.pop("PYLINTRC", None)
    return _linter
Beispiel #18
0
def linter(checker, register, enable, disable, reporter):
    _linter = PyLinter()
    _linter.set_reporter(reporter())
    checkers.initialize(_linter)
    if register:
        register(_linter)
    if checker:
        _linter.register_checker(checker(_linter))
    if disable:
        for msg in disable:
            _linter.disable(msg)
    if enable:
        for msg in enable:
            _linter.enable(msg)
    os.environ.pop("PYLINTRC", None)
    return _linter
Beispiel #19
0
def validate_py3(path_to_module):
    """
    Run pylint python3 validation on the python module/package provided
    """
    with closing(StringIO()) as out:
        linter = PyLinter(reporter=JSONReporter(output=out))
        linter.load_default_plugins()
        linter.python3_porting_mode()
        # Disable `no-absolute-import`, which checks for a behaviour that's already part of python 2.7
        # cf https://www.python.org/dev/peps/pep-0328/
        linter.disable("no-absolute-import")
        with fix_import_path([path_to_module]):
            syspath = sys.path[:]
            try:
                # Remove site-packages from imports. It keeps the standard
                # library, but it prevents pylint from parsing potentially big
                # third party modules.
                sys.path = [p for p in syspath if 'site-packages' not in p]
                linter.check(path_to_module)
            finally:
                sys.path = syspath
            linter.generate_reports()
        raw_results = json.loads(out.getvalue() or "{}")

    results = []
    for problem in raw_results:
        # An issue found by pylint is a dict like
        # {
        #     "message": "Calling a dict.iter*() method",
        #     "obj": "OpenFilesCheck.check",
        #     "column": 27,
        #     "path": "/path/to/file.py",
        #     "line": 235,
        #     "message-id": "W1620",
        #     "type": "warning",
        #     "symbol": "dict-iter-method",co
        #     "module": "file"
        # }
        results.append({
            "message":
            "Line {}, column {}: {}".format(problem["line"], problem["column"],
                                            problem["message"]),
            "path":
            problem["path"],
        })

    return results
Beispiel #20
0
    def execute(self, finder):
        packages = list(finder.packages(filters=self.config['filters']))
        modules = [
            mod for mod in finder.modules(filters=self.config['filters'])
            if os.path.dirname(mod) not in packages
        ]
        targets = modules + finder.topmost_directories(packages)
        if not targets:
            return []

        pylint = PyLinter()

        pylint.load_default_plugins()
        pylint.load_plugin_modules(self.config['options']['plugins'])
        astroid.MANAGER.extension_package_whitelist.update(
            self.config['options']['extension-pkg-whitelist'], )

        reporter = TidyPyReporter(
            pylint.msgs_store,
            filters=self.config['filters'],
            finder=finder,
            targets=targets,
        )
        pylint.set_reporter(reporter)

        for checker in pylint.get_checkers():
            if not hasattr(checker, 'options'):
                continue
            for option in checker.options:
                if option[0] in self.config['options']:
                    checker.set_option(
                        option[0],
                        self.config['options'][option[0]],
                    )

        for disabled in self.config['disabled'] + self.ALWAYS_DISABLED:
            try:
                pylint.disable(disabled)
            except UnknownMessageError:
                pass

        sys_paths = finder.sys_paths(filters=self.config['filters'])
        with mod_sys_path(sys_paths):
            pylint.check(targets)

        return reporter.get_issues()
Beispiel #21
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = cStringIO.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            'C0301:001\n'
            'C0301:002\n')
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  'C0301:001\n'
                                  'C0301:002\n')

    def test_parseable_output_regression(self):
        output = six.StringIO()
        linter = PyLinter(reporter=ParseableTextReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  '0123:1: [C0301(line-too-long), ] '
                                  'Line too long (1/2)\n')
Beispiel #23
0
class PyLinterTC(TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def _compare_messages(self, desc, msg, checkerref=False):
        # replace \r\n with \n, because
        # logilab.common.textutils.normalize_text
        # uses os.linesep, which will
        # not properly compare with triple
        # quoted multilines used in these tests
        self.assertMultiLineEqual(
            desc,
            msg.format_help(checkerref=checkerref).replace('\r\n', '\n'))

    def test_check_message_id(self):
        self.assertIsInstance(self.linter.check_message_id('F0001'),
                              MessageDefinition)
        self.assertRaises(UnknownMessage, self.linter.check_message_id, 'YB12')

    def test_message_help(self):
        msg = self.linter.check_message_id('F0001')
        self._compare_messages(''':fatal (F0001):
  Used when an error occurred preventing the analysis of a module (unable to
  find it for instance). This message belongs to the master checker.''',
                               msg,
                               checkerref=True)
        self._compare_messages(''':fatal (F0001):
  Used when an error occurred preventing the analysis of a module (unable to
  find it for instance).''',
                               msg,
                               checkerref=False)

    def test_message_help_minmax(self):
        # build the message manually to be python version independant
        msg = build_message_def(self.linter._checkers['typecheck'][0], 'E1122',
                                checkers.typecheck.MSGS['E1122'])
        self._compare_messages(
            ''':duplicate-keyword-arg (E1122): *Duplicate keyword argument %r in function call*
  Used when a function call passes the same keyword argument multiple times.
  This message belongs to the typecheck checker. It can't be emitted when using
  Python >= 2.6.''',
            msg,
            checkerref=True)
        self._compare_messages(
            ''':duplicate-keyword-arg (E1122): *Duplicate keyword argument %r in function call*
  Used when a function call passes the same keyword argument multiple times.
  This message can't be emitted when using Python >= 2.6.''',
            msg,
            checkerref=False)

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.linter
        linter.open()
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter._suppression_mapping = {}
        linter.collect_block_lines(astroid, orig_state)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        self.assertEqual(17, linter._suppression_mapping['W0613', 18])
        self.assertEqual(30, linter._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in linter._suppression_mapping)
        self.assertEqual(1, linter._suppression_mapping['C0302', 18])
        self.assertEqual(1, linter._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, linter._suppression_mapping['E1101', 108])
        self.assertEqual(109, linter._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(
            linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value',
                                                  1))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            self.linter.list_messages()
            output = sys.stdout.getvalue()
        finally:
            sys.stdout = sys.__stdout__
        # cursory examination of the output: we're mostly testing it completes
        self.assertIn(':empty-docstring (C0112): *Empty %s docstring*', output)

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_lint_should_analyze_file(self):
        self.linter.set_reporter(text.TextReporter())
        self.linter.config.files_output = True
        self.linter.should_analyze_file = lambda *args: False
        self.linter.check('os')
        self.assertFalse(os.path.exists('pylint_os.txt'))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]

        class TestReporter(object):
            pass

        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142'))
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse(
            'design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue(
            'design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                          'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse(
            'similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in ('design', 'metrics', 'similarities',
                      'imports'):  # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_add_renamed_message(self):
        self.linter.add_renamed_message('C9999', 'old-bad-name',
                                        'invalid-name')
        self.assertEqual('invalid-name',
                         self.linter.check_message_id('C9999').symbol)
        self.assertEqual('invalid-name',
                         self.linter.check_message_id('old-bad-name').symbol)

    def test_renamed_message_register(self):
        class Checker(object):
            msgs = {
                'W1234': ('message', 'msg-symbol', 'msg-description', {
                    'old_names': [('W0001', 'old-symbol')]
                })
            }

        self.linter.register_messages(Checker())
        self.assertEqual('msg-symbol',
                         self.linter.check_message_id('W0001').symbol)
        self.assertEqual('msg-symbol',
                         self.linter.check_message_id('old-symbol').symbol)
Beispiel #24
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            'C0301:001\n'
            'C0301:002\n')

    def test_parseable_output_deprecated(self):
        with testutils.catch_warnings() as cm:
            ParseableTextReporter()

        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)

    def test_html_reporter_deprecated(self):
        with testutils.catch_warnings() as caught:
            HTMLReporter()

        self.assertEqual(len(caught), 1)
        self.assertIsInstance(caught[0].message, DeprecationWarning)
        self.assertEqual(str(caught[0].message),
                         'This reporter will be removed in Pylint 2.0.')

    def test_parseable_output_regression(self):
        output = six.StringIO()
        with testutils.catch_warnings():
            linter = PyLinter(reporter=ParseableTextReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            '0123:1: [C0301(line-too-long), ] '
            'Line too long (1/2)\n')

    def test_html_reporter_msg_template(self):
        expected = '''
<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>category</th>
<th>msg_id</th>
</tr>
<tr class="even">
<td>warning</td>
<td>W0332</td>
</tr>
</table>
</div>
</div>
</body>
</html>'''.strip().splitlines()
        output = six.StringIO()
        with testutils.catch_warnings():
            linter = PyLinter(reporter=HTMLReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('msg-template', '{category}{msg_id}')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('lowercase-l-suffix', line=1)
        linter.reporter.display_messages(Section())
        self.assertEqual(output.getvalue().splitlines(), expected)

    @unittest.expectedFailure
    def test_html_reporter_type(self):
        # Integration test for issue #263
        # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems
        expected = '''<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>type</th>
<th>module</th>
<th>object</th>
<th>line</th>
<th>col_offset</th>
<th>message</th>
</tr>
<tr class="even">
<td>convention</td>
<td>0123</td>
<td>&#160;</td>
<td>1</td>
<td>0</td>
<td>Exactly one space required before comparison
a&lt; 5: print "zero"</td>
</tr>
</table>
</div>
</div>
</body>
</html>
'''
        output = six.StringIO()
        with testutils.catch_warnings():
            linter = PyLinter(reporter=HTMLReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('bad-whitespace',
                           line=1,
                           args=('Exactly one', 'required', 'before',
                                 'comparison', 'a< 5: print "zero"'))
        linter.reporter.display_reports(Section())
        self.assertMultiLineEqual(output.getvalue(), expected)

    def test_display_results_is_renamed(self):
        class CustomReporter(TextReporter):
            def _display(self, layout):
                return None

        reporter = CustomReporter()
        if __pkginfo__.numversion >= (2, 0):
            with self.assertRaises(AttributeError):
                reporter.display_results
        else:
            with testutils.catch_warnings() as cm:
                reporter.display_results(Section())

            self.assertEqual(len(cm), 1)
            self.assertIsInstance(cm[0].message, DeprecationWarning)
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def test_message_help(self):
        msg = self.linter.get_message_help('F0001', checkerref=True)
        expected = ':F0001 (fatal):\n  Used when an error occurred preventing the analysis of a module (unable to\n  find it for instance). This message belongs to the master checker.'
        self.assertMultiLineEqual(msg, expected)
        self.assertRaises(UnknownMessage, self.linter.get_message_help, 'YB12')

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.linter
        linter.open()
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_astroid(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter._suppression_mapping = {}
        linter.collect_block_lines(astroid, orig_state)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        self.assertEqual(17, linter._suppression_mapping['W0613', 18])
        self.assertEqual(30, linter._suppression_mapping['E1101', 33])
        self.assert_(('E1101', 46) not in linter._suppression_mapping)
        self.assertEqual(1, linter._suppression_mapping['C0302', 18])
        self.assertEqual(1, linter._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, linter._suppression_mapping['E1101', 108])
        self.assertEqual(109, linter._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            self.linter.list_messages()
            output = sys.stdout.getvalue()
        finally:
            sys.stdout = sys.__stdout__
        # cursory examination of the output: we're mostly testing it completes
        self.assertTrue(':C0112 (empty-docstring): *Empty %s docstring*' in output)

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]
        class TestReporter(object):
            pass
        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142') )
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                      'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in  ('design', 'metrics', 'similarities',
                       'imports'): # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)
Beispiel #26
0
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  'C0301:001\n'
                                  'C0301:002\n')

    def test_parseable_output_regression(self):
        output = six.StringIO()
        linter = PyLinter(reporter=ParseableTextReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  '0123:1: [C0301(line-too-long), ] '
                                  'Line too long (1/2)\n')

    @unittest.expectedFailure
    def test_html_reporter_type(self):
        # Integration test for issue #263
        # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems
        expected = '''<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>type</th>
<th>module</th>
<th>object</th>
<th>line</th>
<th>col_offset</th>
<th>message</th>
</tr>
<tr class="even">
<td>convention</td>
<td>0123</td>
<td>&#160;</td>
<td>1</td>
<td>0</td>
<td>Exactly one space required before comparison
a&lt; 5: print "zero"</td>
</tr>
</table>
</div>
</div>
</body>
</html>
'''
        output = six.StringIO()
        linter = PyLinter(reporter=HTMLReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('bad-whitespace', line=1,
                           args=('Exactly one', 'required', 'before',
                                 'comparison', 'a< 5: print "zero"'))
        linter.reporter.display_results(Section())
        self.assertMultiLineEqual(output.getvalue(), expected)
Beispiel #27
0
class LintModuleTest:
    maxDiff = None

    def __init__(self,
                 test_file: FunctionalTestFile,
                 config: Optional[Config] = None) -> None:
        _test_reporter = FunctionalTestReporter()
        self._linter = PyLinter()
        self._linter.namespace.persistent = 0
        checkers.initialize(self._linter)

        # See if test has its own .rc file, if so we use that one
        rc_file: Union[Path, str] = PYLINTRC
        try:
            rc_file = test_file.option_file
            self._linter.disable("suppressed-message")
            self._linter.disable("locally-disabled")
            self._linter.disable("useless-suppression")
        except NoFileError:
            pass

        try:
            args = [test_file.source]
        except NoFileError:
            # If we're still raising NoFileError the actual source file doesn't exist
            args = [""]
        _config_initialization(self._linter,
                               args_list=args,
                               config_file=rc_file,
                               reporter=_test_reporter)
        self._test_file = test_file
        self._config = config
        self._check_end_position = (
            sys.version_info >=
            self._test_file.options["min_pyver_end_position"])

    def setUp(self) -> None:
        if self._should_be_skipped_due_to_version():
            pytest.skip(
                f"Test cannot run with Python {sys.version.split(' ', maxsplit=1)[0]}."
            )
        missing = []
        for requirement in self._test_file.options["requires"]:
            try:
                __import__(requirement)
            except ImportError:
                missing.append(requirement)
        if missing:
            pytest.skip(f"Requires {','.join(missing)} to be present.")
        except_implementations = self._test_file.options[
            "except_implementations"]
        if except_implementations:
            if platform.python_implementation() in except_implementations:
                msg = "Test cannot run with Python implementation %r"
                pytest.skip(msg % platform.python_implementation())
        excluded_platforms = self._test_file.options["exclude_platforms"]
        if excluded_platforms:
            if sys.platform.lower() in excluded_platforms:
                pytest.skip(f"Test cannot run on platform {sys.platform!r}")

    def runTest(self) -> None:
        self._runTest()

    def _should_be_skipped_due_to_version(self) -> bool:
        return (sys.version_info < self._test_file.options["min_pyver"]
                or sys.version_info > self._test_file.options["max_pyver"])

    def __str__(self) -> str:
        return f"{self._test_file.base} ({self.__class__.__module__}.{self.__class__.__name__})"

    @staticmethod
    def get_expected_messages(stream: TextIO) -> MessageCounter:
        """Parses a file and get expected messages.

        :param stream: File-like input stream.
        :type stream: enumerable
        :returns: A dict mapping line,msg-symbol tuples to the count on this line.
        :rtype: dict
        """
        messages: MessageCounter = Counter()
        for i, line in enumerate(stream):
            match = _EXPECTED_RE.search(line)
            if match is None:
                continue
            line = match.group("line")
            if line is None:
                lineno = i + 1
            elif line.startswith("+") or line.startswith("-"):
                lineno = i + 1 + int(line)
            else:
                lineno = int(line)

            version = match.group("version")
            op = match.group("op")
            if version:
                required = parse_python_version(version)
                if not _OPERATORS[op](sys.version_info, required):
                    continue

            for msg_id in match.group("msgs").split(","):
                messages[lineno, msg_id.strip()] += 1
        return messages

    @staticmethod
    def multiset_difference(
        expected_entries: MessageCounter,
        actual_entries: MessageCounter,
    ) -> Tuple[MessageCounter, Dict[Tuple[int, str], int]]:
        """Takes two multisets and compares them.

        A multiset is a dict with the cardinality of the key as the value.
        """
        missing = expected_entries.copy()
        missing.subtract(actual_entries)
        unexpected = {}
        for key, value in list(missing.items()):
            if value <= 0:
                missing.pop(key)
                if value < 0:
                    unexpected[key] = -value
        return missing, unexpected

    def _open_expected_file(self) -> TextIO:
        try:
            return open(self._test_file.expected_output, encoding="utf-8")
        except FileNotFoundError:
            return StringIO("")

    def _open_source_file(self) -> TextIO:
        if self._test_file.base == "invalid_encoded_data":
            return open(self._test_file.source, encoding="utf-8")
        if "latin1" in self._test_file.base:
            return open(self._test_file.source, encoding="latin1")
        return open(self._test_file.source, encoding="utf8")

    def _get_expected(self) -> Tuple[MessageCounter, List[OutputLine]]:
        with self._open_source_file() as f:
            expected_msgs = self.get_expected_messages(f)
        if not expected_msgs:
            expected_msgs = Counter()
        with self._open_expected_file() as f:
            expected_output_lines = [
                OutputLine.from_csv(row, self._check_end_position)
                for row in csv.reader(f, "test")
            ]
        return expected_msgs, expected_output_lines

    def _get_actual(self) -> Tuple[MessageCounter, List[OutputLine]]:
        messages: List[Message] = self._linter.reporter.messages
        messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
        received_msgs: MessageCounter = Counter()
        received_output_lines = []
        for msg in messages:
            assert (msg.symbol !=
                    "fatal"), f"Pylint analysis failed because of '{msg.msg}'"
            received_msgs[msg.line, msg.symbol] += 1
            received_output_lines.append(
                OutputLine.from_msg(msg, self._check_end_position))
        return received_msgs, received_output_lines

    def _runTest(self) -> None:
        __tracebackhide__ = True  # pylint: disable=unused-variable
        modules_to_check = [self._test_file.source]
        self._linter.check(modules_to_check)
        expected_messages, expected_output = self._get_expected()
        actual_messages, actual_output = self._get_actual()
        assert (expected_messages == actual_messages
                ), self.error_msg_for_unequal_messages(actual_messages,
                                                       expected_messages,
                                                       actual_output)
        self._check_output_text(expected_messages, expected_output,
                                actual_output)

    def error_msg_for_unequal_messages(
        self,
        actual_messages: MessageCounter,
        expected_messages: MessageCounter,
        actual_output: List[OutputLine],
    ) -> str:
        msg = [f'Wrong results for file "{self._test_file.base}":']
        missing, unexpected = self.multiset_difference(expected_messages,
                                                       actual_messages)
        if missing:
            msg.append("\nExpected in testdata:")
            msg.extend(f" {msg[0]:3}: {msg[1]}" for msg in sorted(missing))
        if unexpected:
            msg.append("\nUnexpected in testdata:")
            msg.extend(f" {msg[0]:3}: {msg[1]}" for msg in sorted(unexpected))
        error_msg = "\n".join(msg)
        if self._config and self._config.getoption("verbose") > 0:
            error_msg += "\n\nActual pylint output for this file:\n"
            error_msg += "\n".join(str(o) for o in actual_output)
        return error_msg

    def error_msg_for_unequal_output(
        self,
        expected_lines: List[OutputLine],
        received_lines: List[OutputLine],
    ) -> str:
        missing = set(expected_lines) - set(received_lines)
        unexpected = set(received_lines) - set(expected_lines)
        error_msg = (f"Wrong output for '{self._test_file.base}.txt':\n"
                     "You can update the expected output automatically with: '"
                     f"python tests/test_functional.py {UPDATE_OPTION} -k "
                     f'"test_functional[{self._test_file.base}]"\'\n\n')
        sort_by_line_number = operator.attrgetter("lineno")
        if missing:
            error_msg += "\n- Missing lines:\n"
            for line in sorted(missing, key=sort_by_line_number):
                error_msg += f"{line}\n"
        if unexpected:
            error_msg += "\n- Unexpected lines:\n"
            for line in sorted(unexpected, key=sort_by_line_number):
                error_msg += f"{line}\n"
        return error_msg

    def _check_output_text(
        self,
        _: MessageCounter,
        expected_output: List[OutputLine],
        actual_output: List[OutputLine],
    ) -> None:
        """This is a function because we want to be able to update the text in LintModuleOutputUpdate."""
        assert expected_output == actual_output, self.error_msg_for_unequal_output(
            expected_output, actual_output)
Beispiel #28
0
class Runner():
    """
    Run and control the checking process.
    """
    outputStream = None
    linter = None
    allowOptions = None
    # Customized checkers.
    checkers = ("header.HeaderChecker",
                "names.TwistedNamesChecker",
                "pycodestyleformat.PyCodeStyleChecker",
                "docstring.DocstringChecker",
                "formattingoperation.FormattingOperationChecker",
                "comment.CommentChecker",
                "testclassname.TestClassNameChecker")
    allowedMessagesFromPylint = ("F0001",
                                 "C0103",
                                 "C0301",
                                 "W0311",
                                 "W0312")
    diffOption = None
    errorResultRead = "Error: Failed to read result file '%s'.\n"
    prefixModuleName = "************* Module "
    regexLineStart = "^[WCEFR]\d{4}\:"

    def __init__(self):
        """
        Initialize C{PyLinter} object, and load configuration file.
        """
        self.allowOptions = True
        self.linter = PyLinter(self._makeOptions())
        # register standard checkers.
        self.linter.load_default_plugins()
        # read configuration.
        pathConfig = os.path.join(twistedchecker.abspath,
                                  "configuration", "pylintrc")
        self.linter.read_config_file(pathConfig)
        # now we can load file config and command line, plugins (which can
        # provide options) have been registered.
        self.linter.load_config_file()
        allowedMessages = self.registerCheckers()
        # disable messages
        disabledMessages = set(self.linter
                           .cfgfile_parser.get("TWISTEDCHECKER", "disable")
                           .replace(" ", "").split(","))
        if disabledMessages != {""}:
            for msg in disabledMessages:
                self.linter.disable(msg)
            allowedMessages -= disabledMessages
        # set default output stream to stdout
        self.setOutput(sys.stdout)
        # set default reporter to limited reporter
        self.setReporter(LimitedReporter(allowedMessages))


    def _makeOptions(self):
        """
        Return options for twistedchecker.
        """
        return (
            ("diff",
             {"type": "string",
              "metavar": "<result-file>",
              "help": "Set comparing result file to automatically "
                      "generate a diff."}
            ),
            ('pep8',
             {'type': 'yn', 'metavar': '<y_or_n>',
              'default': False,
              'help': 'Show pep8 warnings.'}
            ),
            ('strict-epydoc',
             {'type': 'yn', 'metavar': '<y_or_n>',
              'default': False,
              'help': "Check '@type' and '@rtype' in epydoc."}
            ),
          )


    def setOutput(self, stream):
        """
        Set the stream to output result of checking.

        @param stream: output stream, defaultly it should be stdout
        """
        self.outputStream = stream
        sys.stdout = stream


    def setReporter(self, reporter):
        """
        Set the reporter of pylint.

        @param reporter: reporter used to show messages
        """
        self.linter.set_reporter(reporter)


    def displayHelp(self):
        """
        Output help message of twistedchecker.
        """
        self.outputStream.write(self.linter.help())
        sys.exit(32)


    def registerCheckers(self):
        """
        Register all checkers of TwistedChecker to C{PyLinter}.

        @return: a list of allowed messages
        """
        # We patch the default pylint format checker.
        patch_pylint_format.patch()

        # register checkers
        allowedMessages = list(self.allowedMessagesFromPylint)
        for strChecker in self.checkers:
            modname, classname = strChecker.split(".")
            strModule = "twistedchecker.checkers.%s" % modname
            checker = getattr(__import__(strModule,
                                        fromlist=["twistedchecker.checkers"]),
                             classname)
            instanceChecker = checker(self.linter)
            allowedMessages += list(instanceChecker.msgs.keys())
            self.linter.register_checker(instanceChecker)

        self.restrictCheckers(allowedMessages)
        return set(allowedMessages)


    def unregisterChecker(self, checker):
        """
        Remove a checker from the list of registered checkers.

        @param checker: the checker to remove
        """
        self.linter._checkers[checker.name].remove(checker)
        if checker in self.linter._reports:
            del self.linter._reports[checker]
        if checker in self.linter.options_providers:
            self.linter.options_providers.remove(checker)


    def findUselessCheckers(self, allowedMessages):
        """
        Find checkers which generate no allowed messages.

        @param allowedMessages: allowed messages
        @return: useless checkers, remove them from pylint
        """
        uselessCheckers = []
        for checkerName in self.linter._checkers:
            for checker in list(self.linter._checkers[checkerName]):
                messagesOfChecker = set(checker.msgs)
                if not messagesOfChecker.intersection(allowedMessages):
                    uselessCheckers.append(checker)
        return uselessCheckers


    def restrictCheckers(self, allowedMessages):
        """
        Unregister useless checkers to speed up twistedchecker.

        @param allowedMessages: output messages allowed in twistedchecker
        """
        uselessCheckers = self.findUselessCheckers(allowedMessages)
        # Unregister these checkers
        for checker in uselessCheckers:
            self.unregisterChecker(checker)


    def getCheckerByName(self, checkerType):
        """
        Get checker by given name.

        @checkerType: type of the checker
        """
        for checker in sum(list(self.linter._checkers.values()), []):
            if isinstance(checker, checkerType):
                return checker
        return None


    def allowPatternsForNameChecking(self, patternsFunc, patternsClass):
        """
        Allow name exceptions by given patterns.

        @param patternsFunc: patterns of special function names
        @param patternsClass: patterns of special class names
        """
        cfgParser = self.linter.cfgfile_parser
        nameChecker = self.getCheckerByName(NameChecker)
        if not nameChecker:
            return
        if patternsFunc:
            regexFuncAdd = "|((%s).+)$" % "|".join(patternsFunc)
        else:
            regexFuncAdd = ""
        if patternsClass:
            regexClassAdd = "|((%s).+)$" % "|".join(patternsClass)
        else:
            regexClassAdd = ""
        # Modify regex for function, method and class name.
        regexMethod = cfgParser.get("BASIC", "method-rgx") + regexFuncAdd
        regexFunction = cfgParser.get("BASIC", "function-rgx") + regexFuncAdd
        regexClass = cfgParser.get("BASIC", "class-rgx") + regexClassAdd
        # Save to config parser.
        cfgParser.set("BASIC", "method-rgx", regexMethod)
        cfgParser.set("BASIC", "function-rgx", regexFunction)
        cfgParser.set("BASIC", "class-rgx", regexClass)
        # Save to name checker.
        nameChecker.config.method_rgx = re.compile(regexMethod)
        nameChecker.config.function_rgx = re.compile(regexFunction)
        nameChecker.config.class_rgx = re.compile(regexClass)


    def getPathList(self, filesOrModules):
        """
        Transform a list of modules to path.

        @param filesOrModules: a list of modules (may be foo/bar.py or
        foo.bar)
        """
        pathList = []
        for fileOrMod in filesOrModules:
            if not os.path.exists(fileOrMod):
                # May be given module is not not a path,
                # then transform it to a path.
                try:
                    filepath = file_from_modpath(fileOrMod.split('.'))
                except (ImportError, SyntaxError):
                    # Could not load this module.
                    continue
                if not os.path.exists(filepath):
                    # Could not find this module in file system.
                    continue
                if os.path.basename(filepath) == "__init__.py":
                    filepath = os.path.dirname(filepath)
            else:
                filepath = fileOrMod
            pathList.append(filepath)
        return pathList


    def setNameExceptions(self, filesOrModules):
        """
        Find name exceptions in codes and allow them to be ignored
        in checking.

        @param filesOrModules: a list of modules (may be foo/bar.py or
        foo.bar)
        """
        pathList = self.getPathList(filesOrModules)
        for path in pathList:
            patternsFunc, patternsClass = findAllExceptions(path)
            self.allowPatternsForNameChecking(patternsFunc, patternsClass)


    def run(self, args):
        """
        Setup the environment, and run pylint.

        @param args: arguments will be passed to pylint
        @type args: list of string
        """
        # set output stream.
        if self.outputStream:
            self.linter.reporter.set_output(self.outputStream)
        try:
            args = self.linter.load_command_line_configuration(args)
        except SystemExit as exc:
            if exc.code == 2:  # bad options
                exc.code = 32
            raise
        if not args:
            self.displayHelp()
        # Check for 'strict-epydoc' option.
        if self.allowOptions and not self.linter.option_value("strict-epydoc"):
            for msg in ["W9203", "W9205"]:
                self.linter.disable(msg)

        # insert current working directory to the python path to have a correct
        # behaviour.
        sys.path.insert(0, os.getcwd())
        # set exceptions for name checking.
        self.setNameExceptions(args)

        # check for diff option.
        self.diffOption = self.linter.option_value("diff")
        if self.diffOption:
            self.prepareDiff()

        # check codes.
        self.linter.check(args)

        # show diff of warnings if diff option on.
        if self.diffOption:
            diffCount = self.showDiffResults()
            exitCode = 1 if diffCount else 0
            sys.exit(exitCode)

        sys.exit(self.linter.msg_status)


    def prepareDiff(self):
        """
        Prepare to run the checker and get diff results.
        """
        self.streamForDiff = NativeStringIO()
        self.linter.reporter.set_output(self.streamForDiff)


    def showDiffResults(self):
        """
        Show results when diff option on.
        """
        try:
            oldWarnings = self.parseWarnings(self._readDiffFile())
        except:
            sys.stderr.write(self.errorResultRead % self.diffOption)
            return 1

        newWarnings = self.parseWarnings(self.streamForDiff.getvalue())

        diffWarnings = self.generateDiff(oldWarnings, newWarnings)

        if diffWarnings:
            diffResult = self.formatWarnings(diffWarnings)
            self.outputStream.write(diffResult + "\n")
            return len(diffWarnings)
        else:
            return 0

    def _readDiffFile(self):
        """
        Read content of diff file.

        This is here to help with testing.

        @return: File content.
        @rtype: c{str}
        """
        with open(self.diffOption) as f:
            content = f.read()
        return content

    def generateDiff(self, oldWarnings, newWarnings):
        """
        Generate diff between given two lists of warnings.

        @param oldWarnings: parsed old warnings
        @param newWarnings: parsed new warnings
        @return: a dict object of diff
        """
        diffWarnings = {}

        for modulename in newWarnings:
            diffInModule = (
                newWarnings[modulename] -
                oldWarnings.get(modulename, set()))
            if diffInModule:
                diffWarnings[modulename] = diffInModule

        return diffWarnings


    def parseWarnings(self, result):
        """
        Transform result in string to a dict object.

        @param result: a list of warnings in string
        @return: a dict of warnings
        """
        warnings = {}
        currentModule = None
        warningsCurrentModule = []
        for line in result.splitlines():
            if line.startswith(self.prefixModuleName):
                # Save results for previous module
                if currentModule:
                    warnings[currentModule] = set(warningsCurrentModule)
                # Initial results for current module
                moduleName = line.replace(self.prefixModuleName, "")
                currentModule = moduleName
                warningsCurrentModule = []
            elif re.search(self.regexLineStart, line):
                warningsCurrentModule.append(line)
            else:
                if warningsCurrentModule:
                    warningsCurrentModule[-1] += "\n" + line
        # Save warnings for last module
        if currentModule:
            warnings[currentModule] = set(warningsCurrentModule)
        return warnings


    def formatWarnings(self, warnings):
        """
        Format warnings to a list of results.

        @param warnings: a dict of warnings produced by parseWarnings
        @return: a list of warnings in string
        """
        lines = []
        for modulename in sorted(warnings):
            lines.append(self.prefixModuleName + modulename)
            lines.extend(sorted(warnings[modulename],
                         key=lambda x: x.split(":")[1]))

        return "\n".join(lines)
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def _compare_messages(self, desc, msg, checkerref=False):
        # replace \r\n with \n, because
        # logilab.common.textutils.normalize_text
        # uses os.linesep, which will
        # not properly compare with triple
        # quoted multilines used in these tests 
        self.assertMultiLineEqual(desc,
             msg.format_help(checkerref=checkerref)
                .replace('\r\n', '\n'))

    def test_check_message_id(self):
        self.assertIsInstance(self.linter.check_message_id('F0001'),
                              MessageDefinition)
        self.assertRaises(UnknownMessage,
                          self.linter.check_message_id, 'YB12')

    def test_message_help(self):
        msg = self.linter.check_message_id('F0001')
        self._compare_messages(
            ''':fatal (F0001):
  Used when an error occurred preventing the analysis of a module (unable to
  find it for instance). This message belongs to the master checker.''',
            msg, checkerref=True)
        self._compare_messages(
            ''':fatal (F0001):
  Used when an error occurred preventing the analysis of a module (unable to
  find it for instance).''',
            msg, checkerref=False)

    def test_message_help_minmax(self):
        # build the message manually to be python version independant
        msg = build_message_def(self.linter._checkers['typecheck'][0],
                                'E1122', checkers.typecheck.MSGS['E1122'])
        self._compare_messages(
            ''':duplicate-keyword-arg (E1122): *Duplicate keyword argument %r in function call*
  Used when a function call passes the same keyword argument multiple times.
  This message belongs to the typecheck checker. It can't be emitted when using
  Python >= 2.6.''',
            msg, checkerref=True)
        self._compare_messages(
            ''':duplicate-keyword-arg (E1122): *Duplicate keyword argument %r in function call*
  Used when a function call passes the same keyword argument multiple times.
  This message can't be emitted when using Python >= 2.6.''',
            msg, checkerref=False)

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.linter
        linter.open()
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter._suppression_mapping = {}
        linter.collect_block_lines(astroid, orig_state)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        self.assertEqual(17, linter._suppression_mapping['W0613', 18])
        self.assertEqual(30, linter._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in linter._suppression_mapping)
        self.assertEqual(1, linter._suppression_mapping['C0302', 18])
        self.assertEqual(1, linter._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, linter._suppression_mapping['E1101', 108])
        self.assertEqual(109, linter._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            self.linter.list_messages()
            output = sys.stdout.getvalue()
        finally:
            sys.stdout = sys.__stdout__
        # cursory examination of the output: we're mostly testing it completes
        self.assertIn(':empty-docstring (C0112): *Empty %s docstring*', output)

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_lint_should_analyze_file(self):
        self.linter.set_reporter(text.TextReporter())
        self.linter.config.files_output = True
        self.linter.should_analyze_file = lambda *args: False
        self.linter.check('os')
        self.assertFalse(os.path.exists('pylint_os.txt'))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]
        class TestReporter(object):
            pass
        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142') )
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                      'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in  ('design', 'metrics', 'similarities',
                       'imports'): # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_add_renamed_message(self):
        self.linter.add_renamed_message('C9999', 'old-bad-name', 'invalid-name')
        self.assertEqual('invalid-name', 
                         self.linter.check_message_id('C9999').symbol)
        self.assertEqual('invalid-name', 
                         self.linter.check_message_id('old-bad-name').symbol)

    def test_renamed_message_register(self):
         class Checker(object):
              msgs = {'W1234': ('message', 'msg-symbol', 'msg-description',
                                {'old_names': [('W0001', 'old-symbol')]})}
         self.linter.register_messages(Checker())
         self.assertEqual('msg-symbol', 
                          self.linter.check_message_id('W0001').symbol)
         self.assertEqual('msg-symbol', 
                          self.linter.check_message_id('old-symbol').symbol)
Beispiel #30
0
class LintModuleTest:
    maxDiff = None

    def __init__(self, test_file):
        _test_reporter = FunctionalTestReporter()
        self._linter = PyLinter()
        self._linter.set_reporter(_test_reporter)
        self._linter.config.persistent = 0
        checkers.initialize(self._linter)
        self._linter.disable("I")
        try:
            self._linter.read_config_file(test_file.option_file)
            self._linter.load_config_file()
        except NoFileError:
            pass
        self._test_file = test_file

    def setUp(self):
        if self._should_be_skipped_due_to_version():
            pytest.skip("Test cannot run with Python %s." %
                        (sys.version.split(" ")[0], ))
        missing = []
        for req in self._test_file.options["requires"]:
            try:
                __import__(req)
            except ImportError:
                missing.append(req)
        if missing:
            pytest.skip("Requires %s to be present." % (",".join(missing), ))
        if self._test_file.options["except_implementations"]:
            implementations = [
                item.strip() for item in
                self._test_file.options["except_implementations"].split(",")
            ]
            implementation = platform.python_implementation()
            if implementation in implementations:
                pytest.skip("Test cannot run with Python implementation %r" %
                            (implementation, ))
        if self._test_file.options["exclude_platforms"]:
            platforms = [
                item.strip() for item in
                self._test_file.options["exclude_platforms"].split(",")
            ]
            if sys.platform.lower() in platforms:
                pytest.skip("Test cannot run on platform %r" %
                            (sys.platform, ))

    def _should_be_skipped_due_to_version(self):
        return (sys.version_info < self._test_file.options["min_pyver"]
                or sys.version_info > self._test_file.options["max_pyver"])

    def __str__(self):
        return "%s (%s.%s)" % (
            self._test_file.base,
            self.__class__.__module__,
            self.__class__.__name__,
        )

    def _open_expected_file(self):
        return open(self._test_file.expected_output)

    def _open_source_file(self):
        if self._test_file.base == "invalid_encoded_data":
            return open(self._test_file.source)
        if "latin1" in self._test_file.base:
            return open(self._test_file.source, encoding="latin1")
        return open(self._test_file.source, encoding="utf8")

    def _get_expected(self):
        with self._open_source_file() as fobj:
            expected_msgs = get_expected_messages(fobj)

        if expected_msgs:
            with self._open_expected_file() as fobj:
                expected_output_lines = parse_expected_output(fobj)
        else:
            expected_output_lines = []
        return expected_msgs, expected_output_lines

    def _get_received(self):
        messages = self._linter.reporter.messages
        messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
        received_msgs = collections.Counter()
        received_output_lines = []
        for msg in messages:
            assert (msg.symbol !=
                    "fatal"), "Pylint analysis failed because of '{}'".format(
                        msg.msg)
            received_msgs[msg.line, msg.symbol] += 1
            received_output_lines.append(OutputLine.from_msg(msg))
        return received_msgs, received_output_lines

    def _runTest(self):
        modules_to_check = [self._test_file.source]
        self._linter.check(modules_to_check)
        expected_messages, expected_text = self._get_expected()
        received_messages, received_text = self._get_received()

        if expected_messages != received_messages:
            msg = ['Wrong results for file "%s":' % (self._test_file.base)]
            missing, unexpected = multiset_difference(expected_messages,
                                                      received_messages)
            if missing:
                msg.append("\nExpected in testdata:")
                msg.extend(" %3d: %s" % msg for msg in sorted(missing))
            if unexpected:
                msg.append("\nUnexpected in testdata:")
                msg.extend(" %3d: %s" % msg for msg in sorted(unexpected))
            pytest.fail("\n".join(msg))
        self._check_output_text(expected_messages, expected_text,
                                received_text)

    @classmethod
    def _split_lines(cls, expected_messages, lines):
        emitted, omitted = [], []
        for msg in lines:
            if (msg[1], msg[0]) in expected_messages:
                emitted.append(msg)
            else:
                omitted.append(msg)
        return emitted, omitted

    def _check_output_text(self, expected_messages, expected_lines,
                           received_lines):
        expected_lines = self._split_lines(expected_messages,
                                           expected_lines)[0]
        assert (expected_lines == received_lines
                ), "Expected test lines did not match for test: {}".format(
                    self._test_file.base)
Beispiel #31
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            'C0301:001\n'
            'C0301:002\n')

    def test_parseable_output_deprecated(self):
        with warnings.catch_warnings(record=True) as cm:
            warnings.simplefilter("always")
            ParseableTextReporter()

        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)

    def test_parseable_output_regression(self):
        output = six.StringIO()
        with warnings.catch_warnings(record=True):
            linter = PyLinter(reporter=ParseableTextReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(
            output.getvalue(), '************* Module 0123\n'
            '0123:1: [C0301(line-too-long), ] '
            'Line too long (1/2)\n')

    @unittest.expectedFailure
    def test_html_reporter_type(self):
        # Integration test for issue #263
        # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems
        expected = '''<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>type</th>
<th>module</th>
<th>object</th>
<th>line</th>
<th>col_offset</th>
<th>message</th>
</tr>
<tr class="even">
<td>convention</td>
<td>0123</td>
<td>&#160;</td>
<td>1</td>
<td>0</td>
<td>Exactly one space required before comparison
a&lt; 5: print "zero"</td>
</tr>
</table>
</div>
</div>
</body>
</html>
'''
        output = six.StringIO()
        linter = PyLinter(reporter=HTMLReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('bad-whitespace',
                           line=1,
                           args=('Exactly one', 'required', 'before',
                                 'comparison', 'a< 5: print "zero"'))
        linter.reporter.display_results(Section())
        self.assertMultiLineEqual(output.getvalue(), expected)
Beispiel #32
0
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)

    def test_message_help(self):
        msg = self.linter.get_message_help('F0001', checkerref=True)
        expected = ':F0001:\n  Used when an error occurred preventing the analysis of a module (unable to\n  find it for instance). This message belongs to the master checker.'
        self.assertTextEqual(msg, expected)
        self.assertRaises(UnknownMessage, self.linter.get_message_help, 'YB12')

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(not linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        self.assert_(not linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        self.assert_(linter.is_message_enabled('C0121', line=1))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        linter.process_module(open(filepath))
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter.collect_block_lines(linter.get_astng(filepath, 'func_block_disable_msg'), orig_state)
        # global (module level)
        self.assert_(linter.is_message_enabled('W0613'))
        self.assert_(linter.is_message_enabled('E1101'))
        # meth1
        self.assert_(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assert_(not linter.is_message_enabled('W0613', 18))
        # meth3
        self.assert_(not linter.is_message_enabled('E1101', 24))
        self.assert_(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assert_(not linter.is_message_enabled('E1101', 32))
        self.assert_(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assert_(not linter.is_message_enabled('E1101', 42))
        self.assert_(not linter.is_message_enabled('E1101', 43))
        self.assert_(linter.is_message_enabled('E1101', 46))
        self.assert_(not linter.is_message_enabled('E1101', 49))
        self.assert_(not linter.is_message_enabled('E1101', 51))
        # meth6
        self.assert_(not linter.is_message_enabled('E1101', 57))
        self.assert_(linter.is_message_enabled('E1101', 61))
        self.assert_(not linter.is_message_enabled('E1101', 64))
        self.assert_(not linter.is_message_enabled('E1101', 66))

        self.assert_(linter.is_message_enabled('E0602', 57))
        self.assert_(linter.is_message_enabled('E0602', 61))
        self.assert_(not linter.is_message_enabled('E0602', 62))
        self.assert_(linter.is_message_enabled('E0602', 64))
        self.assert_(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assert_(not linter.is_message_enabled('E1101', 70))
        self.assert_(linter.is_message_enabled('E1101', 72))
        self.assert_(linter.is_message_enabled('E1101', 75))
        self.assert_(linter.is_message_enabled('E1101', 77))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            # just invoke it, don't check the output
            self.linter.list_messages()
        finally:
            sys.stdout = sys.__stdout__

    def test_lint_ext_module_with_file_output(self):
        self.linter.config.files_output = True
        try:
            self.linter.check('StringIO')
            self.assert_(os.path.exists('pylint_StringIO.txt'))
            self.assert_(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove('pylint_StringIO.txt')
                os.remove('pylint_global.txt')
            except:
                pass

    def test_enable_report(self):
        self.assertEquals(self.linter.is_report_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEquals(self.linter.is_report_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEquals(self.linter.is_report_enabled('RP0001'), True)

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assert_(not linter.is_message_enabled('C0111'))
        self.assert_(not linter.is_message_enabled('W0142'))
        self.assert_(linter.is_message_enabled('W0113'))

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142') )
        self.assert_(not linter.is_message_enabled('C0111'))
        self.assert_(not linter.is_message_enabled('W0142'))
        self.assert_(linter.is_message_enabled('W0113'))

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.failIf('design' in set([c.name for c in self.linter._get_checkers()]))
        self.linter.enable('design')
        self.failUnless('design' in set([c.name for c in self.linter._get_checkers()]))
Beispiel #33
0
class LintModuleTest:
    maxDiff = None

    def __init__(self, test_file: FunctionalTestFile):
        _test_reporter = FunctionalTestReporter()
        self._linter = PyLinter()
        self._linter.set_reporter(_test_reporter)
        self._linter.config.persistent = 0
        checkers.initialize(self._linter)
        self._linter.disable("I")
        try:
            self._linter.read_config_file(test_file.option_file)
            self._linter.load_config_file()
        except NoFileError:
            pass
        self._test_file = test_file

    def setUp(self):
        if self._should_be_skipped_due_to_version():
            pytest.skip("Test cannot run with Python %s." %
                        sys.version.split(" ")[0])
        missing = []
        for requirement in self._test_file.options["requires"]:
            try:
                __import__(requirement)
            except ImportError:
                missing.append(requirement)
        if missing:
            pytest.skip("Requires %s to be present." % ",".join(missing))
        except_implementations = self._test_file.options[
            "except_implementations"]
        if except_implementations:
            implementations = [
                i.strip() for i in except_implementations.split(",")
            ]
            if platform.python_implementation() in implementations:
                msg = "Test cannot run with Python implementation %r"
                pytest.skip(msg % platform.python_implementation())
        excluded_platforms = self._test_file.options["exclude_platforms"]
        if excluded_platforms:
            platforms = [p.strip() for p in excluded_platforms.split(",")]
            if sys.platform.lower() in platforms:
                pytest.skip("Test cannot run on platform %r" % sys.platform)

    def _should_be_skipped_due_to_version(self):
        return (sys.version_info < self._test_file.options["min_pyver"]
                or sys.version_info > self._test_file.options["max_pyver"])

    def __str__(self):
        return "%s (%s.%s)" % (
            self._test_file.base,
            self.__class__.__module__,
            self.__class__.__name__,
        )

    @staticmethod
    def get_expected_messages(stream):
        """Parses a file and get expected messages.

        :param stream: File-like input stream.
        :type stream: enumerable
        :returns: A dict mapping line,msg-symbol tuples to the count on this line.
        :rtype: dict
        """
        messages = Counter()
        for i, line in enumerate(stream):
            match = _EXPECTED_RE.search(line)
            if match is None:
                continue
            line = match.group("line")
            if line is None:
                line = i + 1
            elif line.startswith("+") or line.startswith("-"):
                line = i + 1 + int(line)
            else:
                line = int(line)

            version = match.group("version")
            op = match.group("op")
            if version:
                required = parse_python_version(version)
                if not _OPERATORS[op](sys.version_info, required):
                    continue

            for msg_id in match.group("msgs").split(","):
                messages[line, msg_id.strip()] += 1
        return messages

    @staticmethod
    def multiset_difference(
            expected_entries: Counter,
            actual_entries: Counter) -> Tuple[Counter, Dict[str, int]]:
        """Takes two multisets and compares them.

        A multiset is a dict with the cardinality of the key as the value."""
        missing = expected_entries.copy()
        missing.subtract(actual_entries)
        unexpected = {}
        for key, value in list(missing.items()):
            if value <= 0:
                missing.pop(key)
                if value < 0:
                    unexpected[key] = -value
        return missing, unexpected

    def _open_expected_file(self):
        try:
            return open(self._test_file.expected_output)
        except FileNotFoundError:
            return StringIO("")

    def _open_source_file(self):
        if self._test_file.base == "invalid_encoded_data":
            return open(self._test_file.source)
        if "latin1" in self._test_file.base:
            return open(self._test_file.source, encoding="latin1")
        return open(self._test_file.source, encoding="utf8")

    def _get_expected(self):
        with self._open_source_file() as f:
            expected_msgs = self.get_expected_messages(f)
        if not expected_msgs:
            return Counter(), []
        with self._open_expected_file() as f:
            expected_output_lines = [
                OutputLine.from_csv(row) for row in csv.reader(f, "test")
            ]
        return expected_msgs, expected_output_lines

    def _get_actual(self):
        messages = self._linter.reporter.messages
        messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
        received_msgs = Counter()
        received_output_lines = []
        for msg in messages:
            assert (msg.symbol !=
                    "fatal"), "Pylint analysis failed because of '{}'".format(
                        msg.msg)
            received_msgs[msg.line, msg.symbol] += 1
            received_output_lines.append(OutputLine.from_msg(msg))
        return received_msgs, received_output_lines

    def _runTest(self):
        modules_to_check = [self._test_file.source]
        self._linter.check(modules_to_check)
        expected_messages, expected_output = self._get_expected()
        actual_messages, actual_output = self._get_actual()
        assert (expected_messages == actual_messages
                ), self.error_msg_for_unequal_messages(actual_messages,
                                                       expected_messages)
        self._check_output_text(expected_messages, expected_output,
                                actual_output)

    def error_msg_for_unequal_messages(self, actual_messages,
                                       expected_messages):
        msg = ['Wrong results for file "%s":' % (self._test_file.base)]
        missing, unexpected = self.multiset_difference(expected_messages,
                                                       actual_messages)
        if missing:
            msg.append("\nExpected in testdata:")
            msg.extend(" %3d: %s" % msg for msg in sorted(missing))
        if unexpected:
            msg.append("\nUnexpected in testdata:")
            msg.extend(" %3d: %s" % msg for msg in sorted(unexpected))
        error_msg = "\n".join(msg)
        return error_msg

    def error_msg_for_unequal_output(self, expected_lines,
                                     received_lines) -> str:
        missing = set(expected_lines) - set(received_lines)
        unexpected = set(received_lines) - set(expected_lines)
        error_msg = (
            "Wrong output for '{_file}.txt':\n"
            "You can update the expected output automatically with: '"
            'python tests/test_functional.py {update_option} -k "test_functional[{_file}]"\'\n\n'
            .format(
                update_option=UPDATE_OPTION,
                _file=self._test_file.base,
            ))
        sort_by_line_number = operator.attrgetter("lineno")
        if missing:
            error_msg += "\n- Missing lines:\n"
            for line in sorted(missing, key=sort_by_line_number):
                error_msg += "{}\n".format(line)
        if unexpected:
            error_msg += "\n- Unexpected lines:\n"
            for line in sorted(unexpected, key=sort_by_line_number):
                error_msg += "{}\n".format(line)
        return error_msg

    def _check_output_text(self, _, expected_output, actual_output):
        """This is a function because we want to be able to update the text in LintModuleOutputUpdate"""
        assert expected_output == actual_output, self.error_msg_for_unequal_output(
            expected_output, actual_output)
Beispiel #34
0
import sys
import platform
import os
from os.path import abspath, dirname, join
import unittest

from pylint.testutils import TestReporter
from pylint.lint import PyLinter
from pylint import checkers
from pylint import epylint

test_reporter = TestReporter()
linter = PyLinter()
linter.set_reporter(test_reporter)
linter.disable("I")
linter.config.persistent = 0
checkers.initialize(linter)

REGR_DATA = join(dirname(abspath(__file__)), "regrtest_data")
sys.path.insert(1, REGR_DATA)


class NonRegrTC(unittest.TestCase):
    def setUp(self):
        """call reporter.finalize() to cleanup
        pending messages if a test finished badly
        """
        linter.reporter.finalize()

    def test_package___path___manipulation(self):
class PyLinterTC(TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def test_message_help(self):
        msg = self.linter.get_message_help('F0001', checkerref=True)
        expected = ':F0001 (fatal):\n  Used when an error occurred preventing the analysis of a module (unable to\n  find it for instance). This message belongs to the master checker.'
        self.assertMultiLineEqual(msg, expected)
        self.assertRaises(UnknownMessage, self.linter.get_message_help, 'YB12')

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.linter
        linter.open()
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_astroid(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter._suppression_mapping = {}
        linter.collect_block_lines(astroid, orig_state)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        self.assertEqual(17, linter._suppression_mapping['W0613', 18])
        self.assertEqual(30, linter._suppression_mapping['E1101', 33])
        self.assert_(('E1101', 46) not in linter._suppression_mapping)
        self.assertEqual(1, linter._suppression_mapping['C0302', 18])
        self.assertEqual(1, linter._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, linter._suppression_mapping['E1101', 108])
        self.assertEqual(109, linter._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(
            linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value',
                                                  1))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            self.linter.list_messages()
            output = sys.stdout.getvalue()
        finally:
            sys.stdout = sys.__stdout__
        # cursory examination of the output: we're mostly testing it completes
        self.assertTrue(
            ':C0112 (empty-docstring): *Empty %s docstring*' in output)

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]

        class TestReporter(object):
            pass

        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142'))
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse(
            'design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue(
            'design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                          'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse(
            'similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in ('design', 'metrics', 'similarities',
                      'imports'):  # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)
Beispiel #36
0
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter(reporter=TextReporter())
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        os.environ.pop('PYLINTRC', None)

    def test_add_message_is_deprecated(self):
        if __pkginfo__.numversion >= (1, 6, 0):
            with self.assertRaises(AttributeError):
                BaseReporter().add_message

        with warnings.catch_warnings(record=True) as cm:
            warnings.simplefilter("always")
            BaseReporter().add_message(None, None, None)
        
        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)
        msg = ('This method is deprecated, use handle_message '
               'instead. It will be removed in Pylint 1.6.')
        self.assertEqual(str(cm[0].message), msg)

    def test_template_option(self):
        output = six.StringIO()
        self.linter.reporter.set_output(output)
        self.linter.set_option('msg-template', '{msg_id}:{line:03d}')
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  'C0301:001\n'
                                  'C0301:002\n')

    def test_parseable_output_deprecated(self):
        with warnings.catch_warnings(record=True) as cm:
            warnings.simplefilter("always")
            ParseableTextReporter()
        
        self.assertEqual(len(cm), 1)
        self.assertIsInstance(cm[0].message, DeprecationWarning)

    def test_parseable_output_regression(self):
        output = six.StringIO()
        with warnings.catch_warnings(record=True):
            linter = PyLinter(reporter=ParseableTextReporter())

        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('output-format', 'parseable')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('line-too-long', line=1, args=(1, 2))
        self.assertMultiLineEqual(output.getvalue(),
                                  '************* Module 0123\n'
                                  '0123:1: [C0301(line-too-long), ] '
                                  'Line too long (1/2)\n')

    def test_html_reporter_msg_template(self):
        expected = '''
<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>category</th>
<th>msg_id</th>
</tr>
<tr class="even">
<td>warning</td>
<td>W0332</td>
</tr>
</table>
</div>
</div>
</body>
</html>'''.strip().splitlines()
        output = six.StringIO()
        linter = PyLinter(reporter=HTMLReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.set_option('msg-template', '{category}{msg_id}')
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('lowercase-l-suffix', line=1)
        linter.reporter.display_results(Section())
        self.assertEqual(output.getvalue().splitlines(), expected)

    @unittest.expectedFailure
    def test_html_reporter_type(self):
        # Integration test for issue #263
        # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems
        expected = '''<html>
<body>
<div>
<div>
<h2>Messages</h2>
<table>
<tr class="header">
<th>type</th>
<th>module</th>
<th>object</th>
<th>line</th>
<th>col_offset</th>
<th>message</th>
</tr>
<tr class="even">
<td>convention</td>
<td>0123</td>
<td>&#160;</td>
<td>1</td>
<td>0</td>
<td>Exactly one space required before comparison
a&lt; 5: print "zero"</td>
</tr>
</table>
</div>
</div>
</body>
</html>
'''
        output = six.StringIO()
        linter = PyLinter(reporter=HTMLReporter())
        checkers.initialize(linter)
        linter.config.persistent = 0
        linter.reporter.set_output(output)
        linter.open()
        linter.set_current_module('0123')
        linter.add_message('bad-whitespace', line=1,
                           args=('Exactly one', 'required', 'before',
                                 'comparison', 'a< 5: print "zero"'))
        linter.reporter.display_results(Section())
        self.assertMultiLineEqual(output.getvalue(), expected)
Beispiel #37
0
class PyLinterTC(TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        linter.file_state = FileState('toto')
        return linter

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.init_linter()
        fs = linter.file_state
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         fs._message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         fs._message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         fs._message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         fs._message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping['W0613', 18])
        self.assertEqual(30, fs._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping['C0302', 18])
        self.assertEqual(1, fs._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping['E1101', 108])
        self.assertEqual(109, fs._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(
            linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value',
                                                  1))

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_lint_should_analyze_file(self):
        self.linter.set_reporter(text.TextReporter())
        self.linter.config.files_output = True
        self.linter.should_analyze_file = lambda *args: False
        self.linter.check('logilab')
        self.assertTrue(os.path.exists('pylint_logilab.txt'))
        self.assertFalse(os.path.exists('pylint_logilab_common.txt'))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]

        class TestReporter(object):
            pass

        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142'))
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse(
            'design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue(
            'design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                          'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse(
            'similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in ('design', 'metrics', 'similarities',
                      'imports'):  # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError, Run, [
            '--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError'
        ])
        self.assertRaises(RuntimeError, Run, [
            '--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant'
        ])

    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(self.datapath('ascript'))
        self.assertEqual(['C:  2: Line too long (175/80)'],
                         self.linter.reporter.messages)
Beispiel #38
0
def test_enable_report(linter: PyLinter) -> None:
    assert linter.report_is_enabled("RP0001")
    linter.disable("RP0001")
    assert not linter.report_is_enabled("RP0001")
    linter.enable("RP0001")
    assert linter.report_is_enabled("RP0001")
Beispiel #39
0
def test_enable_checkers(linter: PyLinter) -> None:
    linter.disable("design")
    assert not ("design" in [c.name for c in linter.prepare_checkers()])
    linter.enable("design")
    assert "design" in [c.name for c in linter.prepare_checkers()]
Beispiel #40
0
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        linter.file_state = FileState('toto')
        return linter

    def test_pylint_visit_method_taken_in_account(self):
        class CustomChecker(checkers.BaseChecker):
            __implements__ = interfaces.IAstroidChecker
            name = 'custom'
            msgs = {'W9999': ('', 'custom', '')}

            @check_messages('custom')
            def visit_class(self, _):
               pass

        self.linter.register_checker(CustomChecker(self.linter))
        self.linter.open()
        out = six.moves.StringIO()
        self.linter.set_reporter(text.TextReporter(out))
        self.linter.check('abc')

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertFalse(linter.is_message_enabled('C0202', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertTrue(linter.is_message_enabled('C0202', line=1))

    def test_message_state_scope(self):
        class FakeConfig(object):
            confidence = ['HIGH']

        linter = self.init_linter()
        linter.disable('C0202')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))
        linter.config = FakeConfig()
        self.assertEqual(
            MSG_STATE_CONFIDENCE,
            linter.get_message_state_scope('this-is-bad',
                                           confidence=interfaces.INFERENCE))

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping['W0613', 18])
        self.assertEqual(30, fs._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping['C0302', 18])
        self.assertEqual(1, fs._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping['E1101', 108])
        self.assertEqual(109, fs._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1))

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        self.linter.config.reports = True
        pylint_strio = 'pylint_%s.txt' % strio
        files = [pylint_strio, 'pylint_global.txt']
        for file in files:
            self.addCleanup(remove, file)

        self.linter.check(strio)
        self.linter.generate_reports()
        for f in files:
            self.assertTrue(os.path.exists(f))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]
        class TestReporter(object):
            pass
        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0234')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0234') )
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'metrics',
                      'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in  ('design', 'metrics', 'similarities'):
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError,
                          Run, ['--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError'])
        self.assertRaises(RuntimeError,
                          Run, ['--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant'])


    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(os.path.join(os.path.dirname(__file__), 'data', 'ascript'))
        self.assertEqual(
            ['C:  2: Line too long (175/100)'],
            self.linter.reporter.messages)

    def test_html_reporter_missing_files(self):
        output = six.StringIO()
        self.linter.set_reporter(html.HTMLReporter(output))
        self.linter.set_option('output-format', 'html')
        self.linter.check('troppoptop.py')
        self.linter.generate_reports()
        value = output.getvalue()
        self.assertIn('troppoptop.py', value)
        self.assertIn('fatal', value)

    def test_python3_checker_disabled(self):
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertNotIn('python3', checker_names)

        self.linter.set_option('enable', 'python3')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertIn('python3', checker_names)
Beispiel #41
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        linter.file_state = FileState('toto')
        return linter

    def test_pylint_visit_method_taken_in_account(self):
        class CustomChecker(checkers.BaseChecker):
            __implements__ = interfaces.IAstroidChecker
            name = 'custom'
            msgs = {'W9999': ('', 'custom', '')}

            @check_messages('custom')
            def visit_class(self, _):
                pass

        self.linter.register_checker(CustomChecker(self.linter))
        self.linter.open()
        out = six.moves.StringIO()
        self.linter.set_reporter(text.TextReporter(out))
        self.linter.check('abc')

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertFalse(linter.is_message_enabled('C0202', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertTrue(linter.is_message_enabled('C0202', line=1))

    def test_message_state_scope(self):
        class FakeConfig(object):
            confidence = ['HIGH']

        linter = self.init_linter()
        linter.disable('C0202')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))
        linter.config = FakeConfig()
        self.assertEqual(
            MSG_STATE_CONFIDENCE,
            linter.get_message_state_scope('this-is-bad',
                                           confidence=interfaces.INFERENCE))

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping['W0613', 18])
        self.assertEqual(30, fs._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping['C0302', 18])
        self.assertEqual(1, fs._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping['E1101', 108])
        self.assertEqual(109, fs._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(
            linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value',
                                                  1))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__,
                         'TextReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0234')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0234'))
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse(
            'design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue(
            'design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(
            ('design', 'format', 'metrics', 'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse(
            'similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in ('design', 'metrics', 'similarities'):
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_addmessage_invalid(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('line-too-long', args=(1, 2))
        self.assertEqual(str(cm.exception),
                         "Message C0301 must provide line, got None")

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('line-too-long',
                                    line=2,
                                    node='fake_node',
                                    args=(1, 2))
        self.assertEqual(
            str(cm.exception),
            "Message C0301 must only provide line, got line=2, node=fake_node")

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('C0321')
        self.assertEqual(str(cm.exception),
                         "Message C0321 must provide Node, got None")

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError, Run, [
            '--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError'
        ])
        self.assertRaises(RuntimeError, Run, [
            '--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant'
        ])

    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(
            os.path.join(os.path.dirname(__file__), 'data', 'ascript'))
        self.assertEqual(['C:  2: Line too long (175/100)'],
                         self.linter.reporter.messages)

    def test_python3_checker_disabled(self):
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertNotIn('python3', checker_names)

        self.linter.set_option('enable', 'python3')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertIn('python3', checker_names)

    def test_full_documentation(self):
        out = six.StringIO()
        self.linter.print_full_documentation(out)
        output = out.getvalue()
        # A few spot checks only
        for re_str in [
                # autogenerated text
                "^Pylint global options and switches$",
                "Verbatim name of the checker is ``python3``",
                # messages
                "^:old-octal-literal \(E1608\):",
                # options
                "^:dummy-variables-rgx:",
        ]:
            regexp = re.compile(re_str, re.MULTILINE)
            self.assertRegexpMatches(output, regexp)
Beispiel #42
0
class Runner():
    """
    Run and control the checking process.
    """
    outputStream = None
    linter = None
    allowOptions = None
    # Customized checkers.
    checkers = ("header.HeaderChecker", "names.TwistedNamesChecker",
                "pycodestyleformat.PyCodeStyleChecker",
                "docstring.DocstringChecker",
                "formattingoperation.FormattingOperationChecker",
                "comment.CommentChecker", "testclassname.TestClassNameChecker")
    allowedMessagesFromPylint = ("F0001", "C0103", "C0301", "W0311", "W0312")
    diffOption = None
    errorResultRead = "Error: Failed to read result file '%s'.\n"
    prefixModuleName = "************* Module "
    regexLineStart = "^[WCEFR]\d{4}\:"

    def __init__(self):
        """
        Initialize C{PyLinter} object, and load configuration file.
        """
        self.allowOptions = True
        self.linter = PyLinter(self._makeOptions())
        # register standard checkers.
        self.linter.load_default_plugins()
        # read configuration.
        pathConfig = os.path.join(twistedchecker.abspath, "configuration",
                                  "pylintrc")
        self.linter.read_config_file(pathConfig)
        # now we can load file config and command line, plugins (which can
        # provide options) have been registered.
        self.linter.load_config_file()
        allowedMessages = self.registerCheckers()
        # disable messages
        disabledMessages = set(
            self.linter.cfgfile_parser.get("TWISTEDCHECKER",
                                           "disable").replace(" ",
                                                              "").split(","))
        if disabledMessages != {""}:
            for msg in disabledMessages:
                self.linter.disable(msg)
            allowedMessages -= disabledMessages
        # set default output stream to stdout
        self.setOutput(sys.stdout)
        # set default reporter to limited reporter
        self.setReporter(LimitedReporter(allowedMessages))

    def _makeOptions(self):
        """
        Return options for twistedchecker.
        """
        return (
            ("diff", {
                "type":
                "string",
                "metavar":
                "<result-file>",
                "help":
                "Set comparing result file to automatically "
                "generate a diff."
            }),
            ('pep8', {
                'type': 'yn',
                'metavar': '<y_or_n>',
                'default': False,
                'help': 'Show pep8 warnings.'
            }),
            ('strict-epydoc', {
                'type': 'yn',
                'metavar': '<y_or_n>',
                'default': False,
                'help': "Check '@type' and '@rtype' in epydoc."
            }),
        )

    def setOutput(self, stream):
        """
        Set the stream to output result of checking.

        @param stream: output stream, defaultly it should be stdout
        """
        self.outputStream = stream
        sys.stdout = stream

    def setReporter(self, reporter):
        """
        Set the reporter of pylint.

        @param reporter: reporter used to show messages
        """
        self.linter.set_reporter(reporter)

    def displayHelp(self):
        """
        Output help message of twistedchecker.
        """
        self.outputStream.write(self.linter.help())
        sys.exit(32)

    def registerCheckers(self):
        """
        Register all checkers of TwistedChecker to C{PyLinter}.

        @return: a list of allowed messages
        """
        # We patch the default pylint format checker.
        patch_pylint_format.patch()

        # register checkers
        allowedMessages = list(self.allowedMessagesFromPylint)
        for strChecker in self.checkers:
            modname, classname = strChecker.split(".")
            strModule = "twistedchecker.checkers.%s" % modname
            checker = getattr(
                __import__(strModule, fromlist=["twistedchecker.checkers"]),
                classname)
            instanceChecker = checker(self.linter)
            allowedMessages += list(instanceChecker.msgs.keys())
            self.linter.register_checker(instanceChecker)

        self.restrictCheckers(allowedMessages)
        return set(allowedMessages)

    def unregisterChecker(self, checker):
        """
        Remove a checker from the list of registered checkers.

        @param checker: the checker to remove
        """
        self.linter._checkers[checker.name].remove(checker)
        if checker in self.linter._reports:
            del self.linter._reports[checker]
        if checker in self.linter.options_providers:
            self.linter.options_providers.remove(checker)

    def findUselessCheckers(self, allowedMessages):
        """
        Find checkers which generate no allowed messages.

        @param allowedMessages: allowed messages
        @return: useless checkers, remove them from pylint
        """
        uselessCheckers = []
        for checkerName in self.linter._checkers:
            for checker in list(self.linter._checkers[checkerName]):
                messagesOfChecker = set(checker.msgs)
                if not messagesOfChecker.intersection(allowedMessages):
                    uselessCheckers.append(checker)
        return uselessCheckers

    def restrictCheckers(self, allowedMessages):
        """
        Unregister useless checkers to speed up twistedchecker.

        @param allowedMessages: output messages allowed in twistedchecker
        """
        uselessCheckers = self.findUselessCheckers(allowedMessages)
        # Unregister these checkers
        for checker in uselessCheckers:
            self.unregisterChecker(checker)

    def getCheckerByName(self, checkerType):
        """
        Get checker by given name.

        @checkerType: type of the checker
        """
        for checker in sum(list(self.linter._checkers.values()), []):
            if isinstance(checker, checkerType):
                return checker
        return None

    def allowPatternsForNameChecking(self, patternsFunc, patternsClass):
        """
        Allow name exceptions by given patterns.

        @param patternsFunc: patterns of special function names
        @param patternsClass: patterns of special class names
        """
        cfgParser = self.linter.cfgfile_parser
        nameChecker = self.getCheckerByName(NameChecker)
        if not nameChecker:
            return
        if patternsFunc:
            regexFuncAdd = "|((%s).+)$" % "|".join(patternsFunc)
        else:
            regexFuncAdd = ""
        if patternsClass:
            regexClassAdd = "|((%s).+)$" % "|".join(patternsClass)
        else:
            regexClassAdd = ""
        # Modify regex for function, method and class name.
        regexMethod = cfgParser.get("BASIC", "method-rgx") + regexFuncAdd
        regexFunction = cfgParser.get("BASIC", "function-rgx") + regexFuncAdd
        regexClass = cfgParser.get("BASIC", "class-rgx") + regexClassAdd
        # Save to config parser.
        cfgParser.set("BASIC", "method-rgx", regexMethod)
        cfgParser.set("BASIC", "function-rgx", regexFunction)
        cfgParser.set("BASIC", "class-rgx", regexClass)
        # Save to name checker.
        nameChecker.config.method_rgx = re.compile(regexMethod)
        nameChecker.config.function_rgx = re.compile(regexFunction)
        nameChecker.config.class_rgx = re.compile(regexClass)

    def getPathList(self, filesOrModules):
        """
        Transform a list of modules to path.

        @param filesOrModules: a list of modules (may be foo/bar.py or
        foo.bar)
        """
        pathList = []
        for fileOrMod in filesOrModules:
            if not os.path.exists(fileOrMod):
                # May be given module is not not a path,
                # then transform it to a path.
                try:
                    filepath = file_from_modpath(fileOrMod.split('.'))
                except (ImportError, SyntaxError):
                    # Could not load this module.
                    continue
                if not os.path.exists(filepath):
                    # Could not find this module in file system.
                    continue
                if os.path.basename(filepath) == "__init__.py":
                    filepath = os.path.dirname(filepath)
            else:
                filepath = fileOrMod
            pathList.append(filepath)
        return pathList

    def setNameExceptions(self, filesOrModules):
        """
        Find name exceptions in codes and allow them to be ignored
        in checking.

        @param filesOrModules: a list of modules (may be foo/bar.py or
        foo.bar)
        """
        pathList = self.getPathList(filesOrModules)
        for path in pathList:
            patternsFunc, patternsClass = findAllExceptions(path)
            self.allowPatternsForNameChecking(patternsFunc, patternsClass)

    def run(self, args):
        """
        Setup the environment, and run pylint.

        @param args: arguments will be passed to pylint
        @type args: list of string
        """
        # set output stream.
        if self.outputStream:
            self.linter.reporter.set_output(self.outputStream)
        try:
            args = self.linter.load_command_line_configuration(args)
        except SystemExit as exc:
            if exc.code == 2:  # bad options
                exc.code = 32
            raise
        if not args:
            self.displayHelp()
        # Check for 'strict-epydoc' option.
        if self.allowOptions and not self.linter.option_value("strict-epydoc"):
            for msg in ["W9203", "W9205"]:
                self.linter.disable(msg)

        # insert current working directory to the python path to have a correct
        # behaviour.
        sys.path.insert(0, os.getcwd())
        # set exceptions for name checking.
        self.setNameExceptions(args)

        # check for diff option.
        self.diffOption = self.linter.option_value("diff")
        if self.diffOption:
            self.prepareDiff()

        # check codes.
        self.linter.check(args)

        # show diff of warnings if diff option on.
        if self.diffOption:
            diffCount = self.showDiffResults()
            exitCode = 1 if diffCount else 0
            sys.exit(exitCode)

        sys.exit(self.linter.msg_status)

    def prepareDiff(self):
        """
        Prepare to run the checker and get diff results.
        """
        self.streamForDiff = NativeStringIO()
        self.linter.reporter.set_output(self.streamForDiff)

    def showDiffResults(self):
        """
        Show results when diff option on.
        """
        try:
            oldWarnings = self.parseWarnings(self._readDiffFile())
        except:
            sys.stderr.write(self.errorResultRead % self.diffOption)
            return 1

        newWarnings = self.parseWarnings(self.streamForDiff.getvalue())

        diffWarnings = self.generateDiff(oldWarnings, newWarnings)

        if diffWarnings:
            diffResult = self.formatWarnings(diffWarnings)
            self.outputStream.write(diffResult + "\n")
            return len(diffWarnings)
        else:
            return 0

    def _readDiffFile(self):
        """
        Read content of diff file.

        This is here to help with testing.

        @return: File content.
        @rtype: c{str}
        """
        with open(self.diffOption) as f:
            content = f.read()
        return content

    def generateDiff(self, oldWarnings, newWarnings):
        """
        Generate diff between given two lists of warnings.

        @param oldWarnings: parsed old warnings
        @param newWarnings: parsed new warnings
        @return: a dict object of diff
        """
        diffWarnings = {}

        for modulename in newWarnings:
            diffInModule = (newWarnings[modulename] -
                            oldWarnings.get(modulename, set()))
            if diffInModule:
                diffWarnings[modulename] = diffInModule

        return diffWarnings

    def parseWarnings(self, result):
        """
        Transform result in string to a dict object.

        @param result: a list of warnings in string
        @return: a dict of warnings
        """
        warnings = {}
        currentModule = None
        warningsCurrentModule = []
        for line in result.splitlines():
            if line.startswith(self.prefixModuleName):
                # Save results for previous module
                if currentModule:
                    warnings[currentModule] = set(warningsCurrentModule)
                # Initial results for current module
                moduleName = line.replace(self.prefixModuleName, "")
                currentModule = moduleName
                warningsCurrentModule = []
            elif re.search(self.regexLineStart, line):
                warningsCurrentModule.append(line)
            else:
                if warningsCurrentModule:
                    warningsCurrentModule[-1] += "\n" + line
        # Save warnings for last module
        if currentModule:
            warnings[currentModule] = set(warningsCurrentModule)
        return warnings

    def formatWarnings(self, warnings):
        """
        Format warnings to a list of results.

        @param warnings: a dict of warnings produced by parseWarnings
        @return: a list of warnings in string
        """
        lines = []
        for modulename in sorted(warnings):
            lines.append(self.prefixModuleName + modulename)
            lines.extend(
                sorted(warnings[modulename], key=lambda x: x.split(":")[1]))

        return "\n".join(lines)
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)

    def test_message_help(self):
        msg = self.linter.get_message_help('F0001', checkerref=True)
        expected = ':F0001:\n  Used when an error occurred preventing the analysis of a module (unable to\n  find it for instance). This message belongs to the master checker.'
        self.assertMultiLineEqual(msg, expected)
        self.assertRaises(UnknownMessage, self.linter.get_message_help, 'YB12')

    def test_enable_message(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(not linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        self.assert_(not linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('C0121'))
        self.assert_(linter.is_message_enabled('C0121', line=1))

    def test_enable_message_block(self):
        linter = self.linter
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astng = linter.get_astng(filepath, 'func_block_disable_msg')
        linter.process_module(astng)
        orig_state = linter._module_msgs_state.copy()
        linter._module_msgs_state = {}
        linter.collect_block_lines(astng, orig_state)
        # global (module level)
        self.assert_(linter.is_message_enabled('W0613'))
        self.assert_(linter.is_message_enabled('E1101'))
        # meth1
        self.assert_(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assert_(not linter.is_message_enabled('W0613', 18))
        # meth3
        self.assert_(not linter.is_message_enabled('E1101', 24))
        self.assert_(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assert_(not linter.is_message_enabled('E1101', 32))
        self.assert_(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assert_(not linter.is_message_enabled('E1101', 42))
        self.assert_(not linter.is_message_enabled('E1101', 43))
        self.assert_(linter.is_message_enabled('E1101', 46))
        self.assert_(not linter.is_message_enabled('E1101', 49))
        self.assert_(not linter.is_message_enabled('E1101', 51))
        # meth6
        self.assert_(not linter.is_message_enabled('E1101', 57))
        self.assert_(linter.is_message_enabled('E1101', 61))
        self.assert_(not linter.is_message_enabled('E1101', 64))
        self.assert_(not linter.is_message_enabled('E1101', 66))

        self.assert_(linter.is_message_enabled('E0602', 57))
        self.assert_(linter.is_message_enabled('E0602', 61))
        self.assert_(not linter.is_message_enabled('E0602', 62))
        self.assert_(linter.is_message_enabled('E0602', 64))
        self.assert_(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assert_(not linter.is_message_enabled('E1101', 70))
        self.assert_(linter.is_message_enabled('E1101', 72))
        self.assert_(linter.is_message_enabled('E1101', 75))
        self.assert_(linter.is_message_enabled('E1101', 77))

    def test_list_messages(self):
        sys.stdout = StringIO()
        try:
            # just invoke it, don't check the output
            self.linter.list_messages()
        finally:
            sys.stdout = sys.__stdout__

    def test_lint_ext_module_with_file_output(self):
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assert_(os.path.exists(pylint_strio))
            self.assert_(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assert_(not linter.is_message_enabled('C0111'))
        self.assert_(not linter.is_message_enabled('W0142'))
        self.assert_(linter.is_message_enabled('W0113'))

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142') )
        self.assert_(not linter.is_message_enabled('C0111'))
        self.assert_(not linter.is_message_enabled('W0142'))
        self.assert_(linter.is_message_enabled('W0113'))

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = tuple(c.name for c in checkers)
        should_not = ('design', 'format', 'imports', 'metrics',
                      'miscellaneous', 'similarities')
        self.assertFalse(any(name in checker_names for name in should_not))

    def test_disable_similar(self):
        # XXX we have to disable them both, that's no good
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        # FIXME should it be necessary to explicitly desactivate failures ?
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        should_not = ('design', 'metrics', 'similarities')
        rest = [name for name in checker_names if name in should_not]
        self.assertListEqual(rest, [])
        self.linter.set_option('disable', 'R,C,W,F')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        should_not +=  ('format', 'imports')
        rest = [name for name in checker_names if name in should_not]
        self.assertListEqual(rest, [])
Beispiel #44
0
class PyLinterTC(TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        linter.file_state = FileState('toto')
        return linter

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertFalse(linter.is_message_enabled('C0121', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0121'))
        self.assertTrue(linter.is_message_enabled('C0121', line=1))

    def test_message_state_scope(self):
        linter = self.init_linter()
        fs = linter.file_state
        linter.disable('C0121')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         fs._message_state_scope('C0121'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         fs._message_state_scope('C0121'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         fs._message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         fs._message_state_scope('W0102', 3))

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping['W0613', 18])
        self.assertEqual(30, fs._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping['C0302', 18])
        self.assertEqual(1, fs._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping['E1101', 108])
        self.assertEqual(109, fs._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1))

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = 'StringIO'
        else:
            strio = 'io'
        self.linter.config.files_output = True
        pylint_strio = 'pylint_%s.txt' % strio
        try:
            self.linter.check(strio)
            self.assertTrue(os.path.exists(pylint_strio))
            self.assertTrue(os.path.exists('pylint_global.txt'))
        finally:
            try:
                os.remove(pylint_strio)
                os.remove('pylint_global.txt')
            except:
                pass

    def test_lint_should_analyze_file(self):
        self.linter.set_reporter(text.TextReporter())
        self.linter.config.files_output = True
        self.linter.should_analyze_file = lambda *args: False
        self.linter.check('logilab')
        self.assertTrue(os.path.exists('pylint_logilab.txt'))
        self.assertFalse(os.path.exists('pylint_logilab_common.txt'))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter')

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]
        class TestReporter(object):
            pass
        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, 'TestReporter'))
        self.linter.set_option('output-format', class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TestReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0142')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0142') )
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0142'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('star-args'))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'imports', 'metrics',
                      'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in  ('design', 'metrics', 'similarities',
                       'imports'): # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError,
                          Run, ['--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError'])
        self.assertRaises(RuntimeError,
                          Run, ['--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant'])


    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(self.datapath('ascript'))
        self.assertEqual(
            ['C:  2: Line too long (175/80)'],
            self.linter.reporter.messages)
Beispiel #45
0
class PyLinterTC(unittest.TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable("I")
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module("toto")
        linter.file_state = FileState("toto")
        return linter

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("W0102"))
        linter.disable("W0101", scope="package")
        linter.disable("W0102", scope="module", line=1)
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertFalse(linter.is_message_enabled("W0102", 1))
        linter.set_current_module("tutu")
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("W0102"))
        linter.enable("W0101", scope="package")
        linter.enable("W0102", scope="module", line=1)
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("W0102", 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("C0121"))
        linter.disable("W", scope="package")
        linter.disable("C", scope="module", line=1)
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("C0121"))
        self.assertFalse(linter.is_message_enabled("C0121", line=1))
        linter.set_current_module("tutu")
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("C0121"))
        linter.enable("W", scope="package")
        linter.enable("C", scope="module", line=1)
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("C0121"))
        self.assertTrue(linter.is_message_enabled("C0121", line=1))

    def test_message_state_scope(self):
        class FakeConfig(object):
            confidence = ["HIGH"]

        linter = self.init_linter()
        linter.disable("C0121")
        self.assertEqual(MSG_STATE_SCOPE_CONFIG, linter.get_message_state_scope("C0121"))
        linter.disable("W0101", scope="module", line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG, linter.get_message_state_scope("C0121"))
        self.assertEqual(MSG_STATE_SCOPE_MODULE, linter.get_message_state_scope("W0101", 3))
        linter.enable("W0102", scope="module", line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE, linter.get_message_state_scope("W0102", 3))
        linter.config = FakeConfig()
        self.assertEqual(
            MSG_STATE_CONFIDENCE, linter.get_message_state_scope("this-is-bad", confidence=interfaces.INFERENCE)
        )

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, "func_block_disable_msg.py")
        linter.set_current_module("func_block_disable_msg")
        astroid = linter.get_ast(filepath, "func_block_disable_msg")
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled("W0613"))
        self.assertTrue(linter.is_message_enabled("E1101"))
        # meth1
        self.assertTrue(linter.is_message_enabled("W0613", 13))
        # meth2
        self.assertFalse(linter.is_message_enabled("W0613", 18))
        # meth3
        self.assertFalse(linter.is_message_enabled("E1101", 24))
        self.assertTrue(linter.is_message_enabled("E1101", 26))
        # meth4
        self.assertFalse(linter.is_message_enabled("E1101", 32))
        self.assertTrue(linter.is_message_enabled("E1101", 36))
        # meth5
        self.assertFalse(linter.is_message_enabled("E1101", 42))
        self.assertFalse(linter.is_message_enabled("E1101", 43))
        self.assertTrue(linter.is_message_enabled("E1101", 46))
        self.assertFalse(linter.is_message_enabled("E1101", 49))
        self.assertFalse(linter.is_message_enabled("E1101", 51))
        # meth6
        self.assertFalse(linter.is_message_enabled("E1101", 57))
        self.assertTrue(linter.is_message_enabled("E1101", 61))
        self.assertFalse(linter.is_message_enabled("E1101", 64))
        self.assertFalse(linter.is_message_enabled("E1101", 66))

        self.assertTrue(linter.is_message_enabled("E0602", 57))
        self.assertTrue(linter.is_message_enabled("E0602", 61))
        self.assertFalse(linter.is_message_enabled("E0602", 62))
        self.assertTrue(linter.is_message_enabled("E0602", 64))
        self.assertTrue(linter.is_message_enabled("E0602", 66))
        # meth7
        self.assertFalse(linter.is_message_enabled("E1101", 70))
        self.assertTrue(linter.is_message_enabled("E1101", 72))
        self.assertTrue(linter.is_message_enabled("E1101", 75))
        self.assertTrue(linter.is_message_enabled("E1101", 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping["W0613", 18])
        self.assertEqual(30, fs._suppression_mapping["E1101", 33])
        self.assertTrue(("E1101", 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping["C0302", 18])
        self.assertEqual(1, fs._suppression_mapping["C0302", 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping["E1101", 108])
        self.assertEqual(109, fs._suppression_mapping["E1101", 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("unreachable"))
        self.assertTrue(linter.is_message_enabled("W0102"))
        self.assertTrue(linter.is_message_enabled("dangerous-default-value"))
        linter.disable("unreachable", scope="package")
        linter.disable("dangerous-default-value", scope="module", line=1)
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertFalse(linter.is_message_enabled("unreachable"))
        self.assertFalse(linter.is_message_enabled("W0102", 1))
        self.assertFalse(linter.is_message_enabled("dangerous-default-value", 1))
        linter.set_current_module("tutu")
        self.assertFalse(linter.is_message_enabled("W0101"))
        self.assertFalse(linter.is_message_enabled("unreachable"))
        self.assertTrue(linter.is_message_enabled("W0102"))
        self.assertTrue(linter.is_message_enabled("dangerous-default-value"))
        linter.enable("unreachable", scope="package")
        linter.enable("dangerous-default-value", scope="module", line=1)
        self.assertTrue(linter.is_message_enabled("W0101"))
        self.assertTrue(linter.is_message_enabled("unreachable"))
        self.assertTrue(linter.is_message_enabled("W0102", 1))
        self.assertTrue(linter.is_message_enabled("dangerous-default-value", 1))

    def test_lint_ext_module_with_file_output(self):
        self.linter.set_reporter(text.TextReporter())
        if sys.version_info < (3, 0):
            strio = "StringIO"
        else:
            strio = "io"
        self.linter.config.files_output = True
        pylint_strio = "pylint_%s.txt" % strio
        files = [pylint_strio, "pylint_global.txt"]
        for file in files:
            self.addCleanup(remove, file)

        self.linter.check(strio)
        self.linter.generate_reports()
        for f in files:
            self.assertTrue(os.path.exists(f))

    def test_lint_should_analyze_file(self):
        self.linter.set_reporter(text.TextReporter())
        self.linter.config.files_output = True
        self.linter.should_analyze_file = lambda *args: False
        self.addCleanup(remove, "pylint_logilab.txt")

        self.linter.check("logilab")
        self.assertTrue(os.path.exists("pylint_logilab.txt"))
        self.assertFalse(os.path.exists("pylint_logilab_common.txt"))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled("RP0001"), True)
        self.linter.disable("RP0001")
        self.assertEqual(self.linter.report_is_enabled("RP0001"), False)
        self.linter.enable("RP0001")
        self.assertEqual(self.linter.report_is_enabled("RP0001"), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option("output-format", "text")
        self.assertEqual(self.linter.reporter.__class__.__name__, "TextReporter")

    def test_report_output_format_custom(self):
        this_module = sys.modules[__name__]

        class TestReporter(object):
            pass

        this_module.TestReporter = TestReporter
        class_name = ".".join((this_module.__name__, "TestReporter"))
        self.linter.set_option("output-format", class_name)
        self.assertEqual(self.linter.reporter.__class__.__name__, "TestReporter")

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option("disable", "C0111,W0142")
        self.assertFalse(linter.is_message_enabled("C0111"))
        self.assertFalse(linter.is_message_enabled("W0142"))
        self.assertTrue(linter.is_message_enabled("W0113"))
        self.assertFalse(linter.is_message_enabled("missing-docstring"))
        self.assertFalse(linter.is_message_enabled("star-args"))
        # no name for W0113

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option("disable", ("C0111", "W0142"))
        self.assertFalse(linter.is_message_enabled("C0111"))
        self.assertFalse(linter.is_message_enabled("W0142"))
        self.assertTrue(linter.is_message_enabled("W0113"))
        self.assertFalse(linter.is_message_enabled("missing-docstring"))
        self.assertFalse(linter.is_message_enabled("star-args"))
        # no name for W0113

    def test_enable_checkers(self):
        self.linter.disable("design")
        self.assertFalse("design" in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable("design")
        self.assertTrue("design" in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(("design", "format", "imports", "metrics", "miscellaneous", "similarities"))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option("disable", "RP0801")
        self.linter.set_option("disable", "R0801")
        self.assertFalse("similarities" in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option("reports", False)
        self.linter.set_option("disable", "R,C,W")
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in ("design", "metrics", "similarities", "imports"):  # as a Fatal message that should be ignored
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module("0123")
        self.linter.add_message("C0301", line=1, args=(1, 2))
        self.linter.add_message("line-too-long", line=2, args=(3, 4))
        self.assertEqual(["C:  1: Line too long (1/2)", "C:  2: Line too long (3/4)"], self.linter.reporter.messages)

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError, Run, ["--load-plugins", "unexistant", "--init-hook", "raise RuntimeError"])
        self.assertRaises(RuntimeError, Run, ["--init-hook", "raise RuntimeError", "--load-plugins", "unexistant"])

    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(os.path.join(os.path.dirname(__file__), "data", "ascript"))
        self.assertEqual(["C:  2: Line too long (175/100)"], self.linter.reporter.messages)

    def test_html_reporter_missing_files(self):
        output = six.StringIO()
        self.linter.set_reporter(html.HTMLReporter(output))
        self.linter.set_option("output-format", "html")
        self.linter.check("troppoptop.py")
        self.linter.generate_reports()
        value = output.getvalue()
        self.assertIn("troppoptop.py", value)
        self.assertIn("fatal", value)

    def test_python3_checker_disabled(self):
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertNotIn("python3", checker_names)

        self.linter.set_option("enable", "python3")
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertIn("python3", checker_names)
Beispiel #46
0
import sys
import os
from os.path import abspath, dirname, join

from logilab.common.testlib import TestCase, unittest_main

from utils import TestReporter

from pylint.lint import PyLinter
from pylint import checkers

test_reporter = TestReporter()
linter = PyLinter()
linter.set_reporter(test_reporter)
linter.disable('I')
linter.config.persistent = 0
checkers.initialize(linter)

REGR_DATA = join(dirname(abspath(__file__)), 'regrtest_data')
sys.path.insert(1, REGR_DATA)

class NonRegrTC(TestCase):
    def setUp(self):
        """call reporter.finalize() to cleanup
        pending messages if a test finished badly
        """
        linter.reporter.finalize()

    def test_package___path___manipulation(self):
        linter.check('package.__init__')
Beispiel #47
0
class PyLinterTC(unittest.TestCase):

    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable('I')
        self.linter.config.persistent = 0
        # register checkers
        checkers.initialize(self.linter)
        self.linter.set_reporter(TestReporter())

    def init_linter(self):
        linter = self.linter
        linter.open()
        linter.set_current_module('toto')
        linter.file_state = FileState('toto')
        return linter

    def test_pylint_visit_method_taken_in_account(self):
        class CustomChecker(checkers.BaseChecker):
            __implements__ = interfaces.IAstroidChecker
            name = 'custom'
            msgs = {'W9999': ('', 'custom', '')}

            @check_messages('custom')
            def visit_class(self, _):
               pass

        self.linter.register_checker(CustomChecker(self.linter))
        self.linter.open()
        out = six.moves.StringIO()
        self.linter.set_reporter(text.TextReporter(out))
        self.linter.check('abc')

    def test_enable_message(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.disable('W0101', scope='package')
        linter.disable('W0102', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        linter.enable('W0101', scope='package')
        linter.enable('W0102', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))

    def test_enable_message_category(self):
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.disable('W', scope='package')
        linter.disable('C', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertFalse(linter.is_message_enabled('C0202', line=1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        linter.enable('W', scope='package')
        linter.enable('C', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('C0202'))
        self.assertTrue(linter.is_message_enabled('C0202', line=1))

    def test_message_state_scope(self):
        class FakeConfig(object):
            confidence = ['HIGH']

        linter = self.init_linter()
        linter.disable('C0202')
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        linter.disable('W0101', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_CONFIG,
                         linter.get_message_state_scope('C0202'))
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0101', 3))
        linter.enable('W0102', scope='module', line=3)
        self.assertEqual(MSG_STATE_SCOPE_MODULE,
                         linter.get_message_state_scope('W0102', 3))
        linter.config = FakeConfig()
        self.assertEqual(
            MSG_STATE_CONFIDENCE,
            linter.get_message_state_scope('this-is-bad',
                                           confidence=interfaces.INFERENCE))

    def test_enable_message_block(self):
        linter = self.init_linter()
        linter.open()
        filepath = join(INPUTDIR, 'func_block_disable_msg.py')
        linter.set_current_module('func_block_disable_msg')
        astroid = linter.get_ast(filepath, 'func_block_disable_msg')
        linter.process_tokens(tokenize_module(astroid))
        fs = linter.file_state
        fs.collect_block_lines(linter.msgs_store, astroid)
        # global (module level)
        self.assertTrue(linter.is_message_enabled('W0613'))
        self.assertTrue(linter.is_message_enabled('E1101'))
        # meth1
        self.assertTrue(linter.is_message_enabled('W0613', 13))
        # meth2
        self.assertFalse(linter.is_message_enabled('W0613', 18))
        # meth3
        self.assertFalse(linter.is_message_enabled('E1101', 24))
        self.assertTrue(linter.is_message_enabled('E1101', 26))
        # meth4
        self.assertFalse(linter.is_message_enabled('E1101', 32))
        self.assertTrue(linter.is_message_enabled('E1101', 36))
        # meth5
        self.assertFalse(linter.is_message_enabled('E1101', 42))
        self.assertFalse(linter.is_message_enabled('E1101', 43))
        self.assertTrue(linter.is_message_enabled('E1101', 46))
        self.assertFalse(linter.is_message_enabled('E1101', 49))
        self.assertFalse(linter.is_message_enabled('E1101', 51))
        # meth6
        self.assertFalse(linter.is_message_enabled('E1101', 57))
        self.assertTrue(linter.is_message_enabled('E1101', 61))
        self.assertFalse(linter.is_message_enabled('E1101', 64))
        self.assertFalse(linter.is_message_enabled('E1101', 66))

        self.assertTrue(linter.is_message_enabled('E0602', 57))
        self.assertTrue(linter.is_message_enabled('E0602', 61))
        self.assertFalse(linter.is_message_enabled('E0602', 62))
        self.assertTrue(linter.is_message_enabled('E0602', 64))
        self.assertTrue(linter.is_message_enabled('E0602', 66))
        # meth7
        self.assertFalse(linter.is_message_enabled('E1101', 70))
        self.assertTrue(linter.is_message_enabled('E1101', 72))
        self.assertTrue(linter.is_message_enabled('E1101', 75))
        self.assertTrue(linter.is_message_enabled('E1101', 77))

        fs = linter.file_state
        self.assertEqual(17, fs._suppression_mapping['W0613', 18])
        self.assertEqual(30, fs._suppression_mapping['E1101', 33])
        self.assertTrue(('E1101', 46) not in fs._suppression_mapping)
        self.assertEqual(1, fs._suppression_mapping['C0302', 18])
        self.assertEqual(1, fs._suppression_mapping['C0302', 50])
        # This is tricky. While the disable in line 106 is disabling
        # both 108 and 110, this is usually not what the user wanted.
        # Therefore, we report the closest previous disable comment.
        self.assertEqual(106, fs._suppression_mapping['E1101', 108])
        self.assertEqual(109, fs._suppression_mapping['E1101', 110])

    def test_enable_by_symbol(self):
        """messages can be controlled by symbolic names.

        The state is consistent across symbols and numbers.
        """
        linter = self.init_linter()
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.disable('unreachable', scope='package')
        linter.disable('dangerous-default-value', scope='module', line=1)
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertFalse(linter.is_message_enabled('W0102', 1))
        self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1))
        linter.set_current_module('tutu')
        self.assertFalse(linter.is_message_enabled('W0101'))
        self.assertFalse(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102'))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value'))
        linter.enable('unreachable', scope='package')
        linter.enable('dangerous-default-value', scope='module', line=1)
        self.assertTrue(linter.is_message_enabled('W0101'))
        self.assertTrue(linter.is_message_enabled('unreachable'))
        self.assertTrue(linter.is_message_enabled('W0102', 1))
        self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1))

    def test_enable_report(self):
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)
        self.linter.disable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), False)
        self.linter.enable('RP0001')
        self.assertEqual(self.linter.report_is_enabled('RP0001'), True)

    def test_report_output_format_aliased(self):
        text.register(self.linter)
        self.linter.set_option('output-format', 'text')
        self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter')

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable', 'C0111,W0234')
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_set_option_2(self):
        linter = self.linter
        linter.set_option('disable', ('C0111', 'W0234') )
        self.assertFalse(linter.is_message_enabled('C0111'))
        self.assertFalse(linter.is_message_enabled('W0234'))
        self.assertTrue(linter.is_message_enabled('W0113'))
        self.assertFalse(linter.is_message_enabled('missing-docstring'))
        self.assertFalse(linter.is_message_enabled('non-iterator-returned'))

    def test_enable_checkers(self):
        self.linter.disable('design')
        self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()])
        self.linter.enable('design')
        self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()])

    def test_errors_only(self):
        linter = self.linter
        self.linter.error_mode()
        checkers = self.linter.prepare_checkers()
        checker_names = set(c.name for c in checkers)
        should_not = set(('design', 'format', 'metrics',
                      'miscellaneous', 'similarities'))
        self.assertSetEqual(set(), should_not & checker_names)

    def test_disable_similar(self):
        self.linter.set_option('disable', 'RP0801')
        self.linter.set_option('disable', 'R0801')
        self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()])

    def test_disable_alot(self):
        """check that we disabled a lot of checkers"""
        self.linter.set_option('reports', False)
        self.linter.set_option('disable', 'R,C,W')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        for cname in  ('design', 'metrics', 'similarities'):
            self.assertFalse(cname in checker_names, cname)

    def test_addmessage(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')
        self.linter.add_message('C0301', line=1, args=(1, 2))
        self.linter.add_message('line-too-long', line=2, args=(3, 4))
        self.assertEqual(
            ['C:  1: Line too long (1/2)', 'C:  2: Line too long (3/4)'],
            self.linter.reporter.messages)

    def test_addmessage_invalid(self):
        self.linter.set_reporter(TestReporter())
        self.linter.open()
        self.linter.set_current_module('0123')

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('line-too-long', args=(1,2))
        self.assertEqual(str(cm.exception),
                         "Message C0301 must provide line, got None")

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('line-too-long', line=2, node='fake_node', args=(1, 2))
        self.assertEqual(str(cm.exception),
                         "Message C0301 must only provide line, got line=2, node=fake_node")

        with self.assertRaises(InvalidMessageError) as cm:
            self.linter.add_message('C0321')
        self.assertEqual(str(cm.exception),
                         "Message C0321 must provide Node, got None")

    def test_init_hooks_called_before_load_plugins(self):
        self.assertRaises(RuntimeError,
                          Run, ['--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError'])
        self.assertRaises(RuntimeError,
                          Run, ['--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant'])


    def test_analyze_explicit_script(self):
        self.linter.set_reporter(TestReporter())
        self.linter.check(os.path.join(os.path.dirname(__file__), 'data', 'ascript'))
        self.assertEqual(
            ['C:  2: Line too long (175/100)'],
            self.linter.reporter.messages)

    def test_python3_checker_disabled(self):
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertNotIn('python3', checker_names)

        self.linter.set_option('enable', 'python3')
        checker_names = [c.name for c in self.linter.prepare_checkers()]
        self.assertIn('python3', checker_names)

    def test_full_documentation(self):
        out = six.StringIO()
        self.linter.print_full_documentation(out)
        output = out.getvalue()
        # A few spot checks only
        for re_str in [
            # autogenerated text
            "^Pylint global options and switches$",
            "Verbatim name of the checker is ``python3``",
            # messages
            "^:old-octal-literal \(E1608\):",
            # options
            "^:dummy-variables-rgx:",
        ]:
            regexp = re.compile(re_str, re.MULTILINE)
            self.assertRegexpMatches(output, regexp)