Example #1
0
    def run_linter(self):
        from pylint.lint import PyLinter
        from pylint import checkers
        from os.path import join

        linter = PyLinter(pylintrc=self.lint_config)

        # same, but not all pylint versions have load_default_plugins
        if hasattr(linter, 'load_default_plugins'):
            linter.load_default_plugins()
        else:
            checkers.initialize(linter)

        linter.read_config_file()
        linter.load_config_file()

        if self.packages:
            self.announce("checking packages", 2)
            report_fn = "packages_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.packages)

            self.announce_overview(linter, report_fn)

        if self.build_scripts:
            self.announce("checking scripts", 2)
            report_fn = "scripts_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.build_scripts)

            self.announce_overview(linter, report_fn)
Example #2
0
def process_file(filename):
    """
    Analyze the file with pylint and write the result
    to a database
    """
    linter = PyLinter()

    checkers.initialize(linter)
    linter.read_config_file()
    linter.quiet = 1

    filemods = linter.expand_files((filename, ))
    if filemods:
        old_stats = config.load_results(filemods[0].get('basename'))
        old_score = old_stats.get('global_note', 0.0)

    linter.check(filename)
    score = eval(linter.config.evaluation, {}, linter.stats)

    # Calculate the credit for both scores
    if score < 0:
        credit = 2.0 * score
    elif score < old_score:
        credit = -1.5 * (old_score - score)
    elif score < MINIMUM_SCORE:
        credit = -1.5 * (MINIMUM_SCORE - score)
    else:
        credit = score - old_score

    return score, old_score, credit
Example #3
0
def test_analyze_explicit_script(linter: PyLinter) -> None:
    linter.set_reporter(testutils.GenericTestReporter())
    linter.check([os.path.join(DATA_DIR, "ascript")])
    assert len(linter.reporter.messages) == 1
    assert linter.reporter.messages[0] == Message(
        msg_id="C0301",
        symbol="line-too-long",
        msg="Line too long (175/100)",
        confidence=interfaces.Confidence(
            name="UNDEFINED",
            description="Warning without any associated confidence level.",
        ),
        location=MessageLocationTuple(
            abspath=os.path.join(abspath(dirname(__file__)),
                                 "ascript").replace(
                                     f"lint{os.path.sep}ascript",
                                     f"data{os.path.sep}ascript"),
            path=f"tests{os.path.sep}data{os.path.sep}ascript",
            module="data.ascript",
            obj="",
            line=2,
            column=0,
            end_line=None,
            end_column=None,
        ),
    )
Example #4
0
def run(files, reporter=None):
    if not reporter:
        reporter = TextReporter()
        reporter.set_output()

    old_writeln = reporter.writeln
    # Shared state.  Python closures are -final-, that is not mutable by reference.
    # However, mutating inner state of the final reference is allowed, so we use a
    # 1 length array to capture this.
    success = [True]

    # If you can believe it, pylint doesn't actually give you any data back on wether a linting
    # run is successful, it expects you to parse output to determine that :'(
    # To compensate, we monkey patch writeln, and flag a failure as any linter resulting in
    # output.
    def new_writeln(*args, **kwds):
        success[0] = False
        return old_writeln(*args, **kwds)

    reporter.__setattr__("writeln", new_writeln)

    linter = PyLinter(reporter=reporter)
    linter.register_checker(ArchimedesDslChecker(linter))
    linter.check(files)
    return success[0]
Example #5
0
def test_multiprocessing(jobs: int) -> None:
    """Check that multiprocessing does not create duplicates."""
    # For the bug (#3584) to show up we need more than one file with issues
    # per process
    filenames = [
        "special_attr_scope_lookup_crash.py",
        "syntax_error.py",
        "unused_variable.py",
        "wildcard.py",
        "wrong_import_position.py",
    ]

    reporter = testutils.GenericTestReporter()
    linter = PyLinter()
    linter.config.jobs = jobs
    linter.config.persistent = 0
    linter.open()
    linter.set_reporter(reporter)

    try:
        sys.path.append(os.path.dirname(REGRTEST_DATA_DIR))
        linter.check(
            [os.path.join(REGRTEST_DATA_DIR, fname) for fname in filenames])
    finally:
        sys.path.pop()

    messages = reporter.messages
    assert len(messages) == len(set(messages))
Example #6
0
def process_file(filename):
    """
    Analyze the file with pylint and write the result
    to a database
    """
    linter = PyLinter()

    checkers.initialize(linter)
    linter.read_config_file()
    linter.quiet = 1

    filemods = linter.expand_files((filename, ))
    if filemods:
        old_stats = config.load_results(filemods[0].get('basename'))
        old_score = old_stats.get('global_note', 0.0)

    linter.check(filename)
    score = eval(linter.config.evaluation, {}, linter.stats)

    # Calculate the credit for both scores
    if score < 0:
        credit = 2.0 * score
    elif score < old_score:
        credit = -1.5 * (old_score - score)
    elif score < MINIMUM_SCORE:
        credit = -1.5 * (MINIMUM_SCORE - score)
    else:
        credit = score - old_score

    return score, old_score, credit
Example #7
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))
Example #8
0
def test_checker_dep_graphs(linter: PyLinter) -> None:
    linter.set_option("persistent", False)
    linter.set_option("reports", True)
    linter.set_option("enable", "imports")
    linter.set_option("import_graph", "import.dot")
    linter.set_option("ext_import_graph", "ext_import.dot")
    linter.set_option("int_import_graph", "int_import.dot")
    linter.check(["input"])
    linter.generate_reports()
    assert exists("import.dot")
    assert exists("ext_import.dot")
    assert exists("int_import.dot")
Example #9
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()
Example #10
0
def test_pylint_visit_method_taken_in_account(linter: PyLinter) -> None:
    class CustomChecker(checkers.BaseChecker):
        name = "custom"
        msgs = {"W9999": ("", "custom", "")}

        @only_required_for_messages("custom")
        def visit_class(self, _):
            pass

    linter.register_checker(CustomChecker(linter))
    linter.open()
    out = StringIO()
    linter.set_reporter(text.TextReporter(out))
    linter.check(["abc"])
Example #11
0
    def check_pylint(self):
        """
        Check using pylint.
        """
        options = self.options.get('pylint', self.file_path).copy()
        if not options['enabled']:
            return
        del options['enabled']

        if not self._compiled_tree:
            # We failed to compile the tree.
            return

        from pylint.lint import PyLinter, fix_import_path
        from pylint.reporters import CollectingReporter

        linter = PyLinter()
        linter.load_default_plugins()
        linter.set_reporter(CollectingReporter())

        if options['py3k']:
            linter.python3_porting_mode()
        del options['py3k']

        rcfile = options.get('rcfile', None)
        del options['rcfile']

        if rcfile:
            linter.read_config_file(config_file=rcfile)
            linter.load_config_file()
        else:
            linter.load_configuration_from_config(options)

        # PyLint does its own import and parsing, so we only pass the file
        # name and the precompiled tree.
        with fix_import_path(self.file_path):
            linter.check(self.file_path)

        for message in linter.reporter.messages:
            self.message(
                message.line,
                '%s:%s %s' % (
                    message.msg_id,
                    message.symbol,
                    message.msg,
                    ),
                code=message.msg_id,
                icon='info',
                category='pylint',
                )
Example #12
0
def test_pylint_visit_method_taken_in_account(linter: PyLinter) -> None:
    class CustomChecker(checkers.BaseChecker):
        __implements__ = interfaces.IAstroidChecker
        name = "custom"
        msgs = {"W9999": ("", "custom", "")}

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

    linter.register_checker(CustomChecker(linter))
    linter.open()
    out = StringIO()
    linter.set_reporter(text.TextReporter(out))
    linter.check(["abc"])
Example #13
0
def test_checker_dep_graphs(linter: PyLinter) -> None:
    linter.global_set_option("persistent", False)
    linter.global_set_option("reports", True)
    linter.global_set_option("enable", "imports")
    linter.global_set_option("import-graph", "import.dot")
    linter.global_set_option("ext-import-graph", "ext_import.dot")
    linter.global_set_option("int-import-graph", "int_import.dot")
    linter.global_set_option("int-import-graph", "int_import.dot")
    # ignore this file causing spurious MemoryError w/ some python version (>=2.3?)
    linter.global_set_option("ignore", ("func_unknown_encoding.py", ))
    linter.check(["input"])
    linter.generate_reports()
    assert exists("import.dot")
    assert exists("ext_import.dot")
    assert exists("int_import.dot")
Example #14
0
def main():
    linter = PyLinter()
    # linter.msgs = get_msg_ids(error_level)
    ns = parse_arguments()
    for mod in ns.module:
        print("module = %s" % mod)
        print(linter.check(mod))
Example #15
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
Example #16
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()
Example #17
0
def main():
    """Run the Wall code quality checks."""
    print("Running unit tests...")
    # TODO: tests = defaultTestLoader.discover('.')
    tests = defaultTestLoader.loadTestsFromNames(["wall", "wall.util", "wall.bricks.url"])
    test_result = TextTestRunner(stream=sys.stdout).run(tests)

    print("\nLinting (Python)...")
    linter = PyLinter()
    linter.load_default_plugins()
    linter.load_file_configuration()
    linter.load_configuration(ignore="lib")
    # TODO: linter.check(['wall', 'walld.py', 'sjmpc.py', 'check.py'])
    linter.check(["wall.util", "walld.py", "check.py"])

    print("\nLinting (text)...")
    checkre_result = checkre(
        {
            (
                r"(?!.*/lib/).*\.(html|css)",
                r"wall/res/default.cfg",
                r"wall/res/static/(display|remote)/config.default.json",
                r"pylintrc",
            ): (
                line_length_check(),
                simple_indentation_check(),
                trailing_space_check(),
                whitespace_check(),
                newline_at_eof_check(),
            ),
            r"(?!.*/lib/).*\.md": (
                line_length_check(),
                trailing_space_check(),
                whitespace_check(),
                newline_at_eof_check(),
            ),
            r"(?!.*/lib/|walld.py|sjmpc.py|check.py).*\.py": header_check("wall/__init__.py", 2),
            r"(?!.*/lib/).*\.js": header_check("wall/res/static/wall.js", 4),
        }
    )

    if not test_result.wasSuccessful() or linter.msg_status != 0 or checkre_result != 0:
        return 1

    print("\nEverything looks fine, good work!")
    return 0
def main(args):
    if len(args) != 2:
        print('Usage: %s /path/to/python/code' % args[0])
        sys.exit(1)

    # Need to add tis script's directory to the Python path so that this module
    # can be made available to Pylint
    sys.path.append(FILE_DIR)

    linter = PyLinter()

    linter.load_default_plugins()
    linter.load_plugin_modules([THIS_MODULE])

    linter.read_config_file(PYLINT_RC_PATH)
    linter.load_config_file()

    linter.check(args[1])
    linter.generate_reports()
    def run_linter(self):
        linter = PyLinter(pylintrc=self.lint_config)

        # load_default_plugins will call checkers.initialize if
        # implemented, but some older versions of pylint don't have
        # this method so we fall back to calling is manually.
        if hasattr(linter, 'load_default_plugins'):
            linter.load_default_plugins()
        else:
            checkers.initialize(linter)

        linter.read_config_file()
        linter.load_config_file()

        # don't emit messages about suppressed or useless suppressed
        # configs, it's just annoying and doesn't help.
        #linter.disable('suppressed-message')
        #linter.disable('useless-suppression')

        if self.packages:
            self.announce("pylint is checking packages", 2)
            report_fn = "packages_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.packages)

            self.announce_overview(linter, report_fn)

        if self.build_scripts:
            self.announce("pylint is checking scripts", 2)
            report_fn = "scripts_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.build_scripts)

            self.announce_overview(linter, report_fn)
Example #20
0
    def run_linter(self):
        linter = PyLinter(pylintrc=self.lint_config)

        # load_default_plugins will call checkers.initialize if
        # implemented, but some older versions of pylint don't have
        # this method so we fall back to calling is manually.
        if hasattr(linter, 'load_default_plugins'):
            linter.load_default_plugins()
        else:
            checkers.initialize(linter)

        linter.read_config_file()
        linter.load_config_file()

        # don't emit messages about suppressed or useless suppressed
        # configs, it's just annoying and doesn't help.
        #linter.disable('suppressed-message')
        #linter.disable('useless-suppression')

        if self.packages:
            self.announce("pylint is checking packages", 2)
            report_fn = "packages_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.packages)

            self.announce_overview(linter, report_fn)

        if self.build_scripts:
            self.announce("pylint is checking scripts", 2)
            report_fn = "scripts_report." + linter.reporter.extension
            report_fn = join(self.build_base, report_fn)
            with open(report_fn, "wt") as out:
                linter.reporter.set_output(out)
                linter.check(self.build_scripts)

            self.announce_overview(linter, report_fn)
Example #21
0
class PyLinterTC(TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable_message_category("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_message("W0101", scope="package")
        linter.disable_message("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_message("W0101", scope="package")
        linter.enable_message("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("R0102"))
        linter.disable_message_category("W", scope="package")
        linter.disable_message_category("R", scope="module")
        self.assert_(not linter.is_message_enabled("W0101"))
        self.assert_(not linter.is_message_enabled("R0102"))
        linter.set_current_module("tutu")
        self.assert_(not linter.is_message_enabled("W0101"))
        self.assert_(linter.is_message_enabled("R0102"))
        linter.enable_message_category("W", scope="package")
        linter.enable_message_category("R", scope="module")
        self.assert_(linter.is_message_enabled("W0101"))
        self.assert_(linter.is_message_enabled("R0102"))

    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("R0001"), True)
        self.linter.disable_report("R0001")
        self.assertEquals(self.linter.is_report_enabled("R0001"), False)
        self.linter.enable_report("R0001")
        self.assertEquals(self.linter.is_report_enabled("R0001"), True)

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option("disable-msg", "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-msg", ("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_checkers1(self):
        self.linter.enable_checkers(["design"], False)
        self.assertEquals(
            sorted([c.name for c in self.linter._checkers.values() if c.is_enabled()]),
            [
                "basic",
                "classes",
                "exceptions",
                "format",
                "imports",
                "logging",
                "master",
                "metrics",
                "miscellaneous",
                "newstyle",
                "similarities",
                "string_format",
                "typecheck",
                "variables",
            ],
        )

    def test_enable_checkers2(self):
        self.linter.enable_checkers(["design"], True)
        self.assertEquals(
            sorted([c.name for c in self.linter._checkers.values() if c.is_enabled()]), ["design", "master"]
        )
Example #22
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)
Example #23
0
#!/usr/bin/env python
from pylint.lint import PyLinter
from pylint import checkers

linter = PyLinter()

checkers.initialize(linter)
linter.quiet = 999
linter.check("errors.py")
s=linter.stats
Example #24
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)
Example #25
0
class LintModuleTest:
    def __init__(self, test_file: Tuple[str, Path]) -> None:
        self._test_file = test_file

        _test_reporter = FunctionalTestReporter()

        self._linter = PyLinter()
        self._linter.config.persistent = 0
        checkers.initialize(self._linter)

        # Check if this message has a custom configuration file (e.g. for enabling optional checkers).
        # If not, use the default configuration.
        config_file: Optional[Path]
        msgid, full_path = test_file
        pylintrc = full_path.parent / "pylintrc"
        if pylintrc.exists():
            config_file = pylintrc
        else:
            config_file = next(config.find_default_config_files(), None)
        args = [
            str(full_path),
            "--disable=all",
            f"--enable={msgid},astroid-error,fatal,syntax-error",
        ]
        print(f"Command used:\npylint {' '.join(args)}")
        _config_initialization(
            self._linter,
            args_list=args,
            reporter=_test_reporter,
            config_file=config_file,
        )

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

    def is_good_test_file(self) -> bool:
        return self._test_file[1].name == "good.py"

    def is_bad_test_file(self) -> bool:
        return self._test_file[1].name == "bad.py"

    @staticmethod
    def get_expected_messages(stream: TextIO) -> MessageCounter:
        """Parse a file and get expected messages."""
        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)

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

    def _get_expected(self) -> MessageCounter:
        """Get the expected messages for a file."""
        with open(self._test_file[1], encoding="utf8") as f:
            expected_msgs = self.get_expected_messages(f)
        return expected_msgs

    def _get_actual(self) -> MessageCounter:
        """Get the actual messages after a run."""
        messages: List[Message] = self._linter.reporter.messages
        messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
        received_msgs: MessageCounter = Counter()
        for msg in messages:
            received_msgs[msg.line, msg.symbol] += 1
        return received_msgs

    def _runTest(self) -> None:
        """Run the test and assert message differences."""
        self._linter.check([str(self._test_file[1])])
        expected_messages = self._get_expected()
        actual_messages = self._get_actual()
        if self.is_good_test_file():
            msg = "There should be no warning raised for 'good.py'"
            assert actual_messages.total() == 0, msg  # type: ignore[attr-defined]
        if self.is_bad_test_file():
            msg = "There should be at least one warning raised for 'bad.py'"
            assert actual_messages.total() > 0, msg  # type: ignore[attr-defined]
        assert expected_messages == actual_messages
Example #26
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)
Example #27
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)
Example #28
0
#!/usr/bin/env python

from cStringIO import StringIO
from pylint.lint import PyLinter
from pylint.reporters.text import ParseableTextReporter

l = PyLinter()


reporter = ParseableTextReporter()
result = StringIO()
reporter.set_output(result)
l.check(__file__)
Example #29
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)
Example #30
0
class PyLinterTC(TestCase):
    def setUp(self):
        self.linter = PyLinter()
        self.linter.disable_message_category('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_message('W0101', scope='package')
        linter.disable_message('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_message('W0101', scope='package')
        linter.enable_message('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('R0102'))
        linter.disable_message_category('W', scope='package')
        linter.disable_message_category('R', scope='module')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(not linter.is_message_enabled('R0102'))
        linter.set_current_module('tutu')
        self.assert_(not linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('R0102'))
        linter.enable_message_category('W', scope='package')
        linter.enable_message_category('R', scope='module')
        self.assert_(linter.is_message_enabled('W0101'))
        self.assert_(linter.is_message_enabled('R0102'))

    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('R0001'), True)
        self.linter.disable_report('R0001')
        self.assertEquals(self.linter.is_report_enabled('R0001'), False)
        self.linter.enable_report('R0001')
        self.assertEquals(self.linter.is_report_enabled('R0001'), True)

    def test_set_option_1(self):
        linter = self.linter
        linter.set_option('disable-msg', '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-msg', ('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_checkers1(self):
        self.linter.enable_checkers(['design'], False)
        self.assertEquals(
            sorted([
                c.name for c in self.linter._checkers.values()
                if c.is_enabled()
            ]), [
                'basic', 'classes', 'exceptions', 'format', 'imports',
                'logging', 'master', 'metrics', 'miscellaneous', 'newstyle',
                'similarities', 'string_format', 'typecheck', 'variables'
            ])

    def test_enable_checkers2(self):
        self.linter.enable_checkers(['design'], True)
        self.assertEquals(
            sorted([
                c.name for c in self.linter._checkers.values()
                if c.is_enabled()
            ]), ['design', 'master'])
class LintModuleTest:
    def __init__(self, test_file: Tuple[str, Path]) -> None:
        self._test_file = test_file

        _test_reporter = FunctionalTestReporter()

        self._linter = PyLinter()
        self._linter.namespace.persistent = 0
        checkers.initialize(self._linter)

        # Check if this message has a custom configuration file (e.g. for enabling optional checkers).
        # If not, use the default configuration.
        config_file: Optional[Path]
        if (test_file[1].parent / "pylintrc").exists():
            config_file = test_file[1].parent / "pylintrc"
        else:
            config_file = next(config.find_default_config_files(), None)

        _config_initialization(
            self._linter,
            args_list=[
                str(test_file[1]),
                "--disable=all",
                f"--enable={test_file[0]}",
            ],
            reporter=_test_reporter,
            config_file=config_file,
        )

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

    def is_good_test_file(self) -> bool:
        return self._test_file[1].name == "good.py"

    def is_bad_test_file(self) -> bool:
        return self._test_file[1].name == "bad.py"

    @staticmethod
    def get_expected_messages(stream: TextIO) -> MessageCounter:
        """Parse a file and get expected messages."""
        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
            else:
                lineno = int(line)

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

    def _get_expected(self) -> MessageCounter:
        """Get the expected messages for a file."""
        with open(self._test_file[1], encoding="utf8") as f:
            expected_msgs = self.get_expected_messages(f)
        return expected_msgs

    def _get_actual(self) -> MessageCounter:
        """Get the actual messages after a run."""
        messages: List[Message] = self._linter.reporter.messages
        messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
        received_msgs: MessageCounter = Counter()
        for msg in messages:
            received_msgs[msg.line, msg.symbol] += 1
        return received_msgs

    def _runTest(self) -> None:
        """Run the test and assert message differences."""
        self._linter.check([str(self._test_file[1])])
        expected_messages = self._get_expected()
        actual_messages = self._get_actual()
        if self.is_good_test_file():
            assert actual_messages.total() == 0  # type: ignore[attr-defined]
        if self.is_bad_test_file():
            assert actual_messages.total() > 0  # type: ignore[attr-defined]
        assert expected_messages == actual_messages
Example #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()]))
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)
Example #34
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)
Example #35
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)
Example #36
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 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)
Example #37
0
def test_analyze_explicit_script(linter: PyLinter) -> None:
    linter.set_reporter(testutils.GenericTestReporter())
    linter.check([os.path.join(DATA_DIR, "ascript")])
    assert ["C:  2: Line too long (175/100)"] == linter.reporter.messages
Example #38
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)
Example #39
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)
Example #40
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)
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, [])
Example #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)
Example #43
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)
Example #44
0
    def test_sequential_checkers_work(self) -> None:
        """Tests original basic types of checker works as expected in -jN.

        This means that a sequential checker should return the same data for a given
        file-stream irrespective of whether it's run in -j1 or -jN
        """
        linter = PyLinter(reporter=Reporter())

        # Add a sequential checker to ensure it records data against some streams
        linter.register_checker(SequentialTestChecker(linter))

        # Create a dummy file, the actual contents of which will be ignored by the
        # register test checkers, but it will trigger at least a single-job to be run.
        single_file_container = _gen_file_datas(count=1)

        # Invoke the lint process in a multiprocess way, although we only specify one
        # job.
        check_parallel(
            linter,
            jobs=1,
            files=iter(single_file_container),
            arguments=["--enable", "R9999"],
        )
        assert len(linter.get_checkers()) == 2, (
            "We should only have the 'master' and 'sequential-checker' "
            "checkers registered")
        assert {
            "--test-file_data-name-0--": {
                "convention": 0,
                "error": 0,
                "fatal": 0,
                "info": 0,
                "refactor": 0,
                "statement": 18,
                "warning": 0,
            }
        } == linter.stats.by_module
        assert not linter.stats.by_msg
        assert linter.stats.convention == 0
        assert linter.stats.error == 0
        assert linter.stats.fatal == 0
        assert linter.stats.info == 0
        assert linter.stats.refactor == 0
        assert linter.stats.statement == 18
        assert linter.stats.warning == 0

        # now run the regular mode of checking files and check that, in this proc, we
        # collect the right data
        filepath = [single_file_container[0][1]]  # get the filepath element
        linter.check(filepath)
        assert {
            "input.similar1": {  # module is the only change from previous
                "convention": 0,
                "error": 0,
                "fatal": 0,
                "info": 0,
                "refactor": 0,
                "statement": 18,
                "warning": 0,
            }
        } == linter.stats.by_module
        assert not linter.stats.by_msg
        assert linter.stats.convention == 0
        assert linter.stats.error == 0
        assert linter.stats.fatal == 0
        assert linter.stats.info == 0
        assert linter.stats.refactor == 0
        assert linter.stats.statement == 18
        assert linter.stats.warning == 0
Example #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_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)