def register(linter: PyLinter): """This required method auto registers the checker. :param linter: The linter to register the checker to. :type linter: pylint.lint.PyLinter """ linter.register_checker(ConfusingConsecutiveElifChecker(linter))
def setUpClass(cls): cls.linter_class = PyLinter cls.mixin = PyLinter.__bases__[1] cls.mixin_name = PyLinter.__bases__[1].__name__ linter = PyLinter() linter._do_load() cls.linter = linter
def test_baseline_benchmark_j1_single_working_checker(self, benchmark): """Establish a baseline of single-worker performance for PyLinter. Here we mimic a single Checker that does some work so that we can see the impact of running a simple system with -j1 against the same system with -j2. We expect this benchmark to take very close to `numfiles*SleepingChecker.sleep_duration` """ if benchmark.disabled: benchmark(print, "skipping, do not want to sleep in main tests") return # _only_ run this test is profiling linter = PyLinter(reporter=Reporter()) linter.register_checker(SleepingChecker(linter)) # Check the same number of files as # `test_baseline_benchmark_j2_single_working_checker` fileinfos = [self.empty_filepath for _ in range(2)] assert linter.config.jobs == 1 assert len(linter._checkers) == 2, "Should have 'main' and 'sleeper'" benchmark(linter.check, fileinfos) assert ( linter.msg_status == 0 ), f"Expected no errors to be thrown: {pprint.pformat(linter.reporter.messages)}"
def setUp(self): self.linter = PyLinter(reporter=TextReporter()) self.linter.disable('I') self.linter.config.persistent = 0 # register checkers checkers.initialize(self.linter) os.environ.pop('PYLINTRC', None)
def test_baseline_benchmark_j2_single_working_checker(self, benchmark): """Establishes baseline of multi-worker performance for PyLinter/check_parallel. We expect this benchmark to take less time that test_baseline_benchmark_j1, `error_margin*(1/J)*(numfiles*SleepingChecker.sleep_duration)` Because of the cost of the framework and system the performance difference will *not* be 1/2 of -j1 versions. """ if benchmark.disabled: benchmark(print, "skipping, do not want to sleep in main tests") return # _only_ run this test is profiling linter = PyLinter(reporter=Reporter()) linter.config.jobs = 2 linter.register_checker(SleepingChecker(linter)) # Check the same number of files as # `test_baseline_benchmark_j1_single_working_checker` fileinfos = [self.empty_filepath for _ in range(2)] assert linter.config.jobs == 2 assert len(linter._checkers) == 2, "Should have 'main' and 'sleeper'" benchmark(linter.check, fileinfos) assert ( linter.msg_status == 0 ), f"Expected no errors to be thrown: {pprint.pformat(linter.reporter.messages)}"
def test_html_reporter_msg_template(self): expected = ''' <html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>category</th> <th>msg_id</th> </tr> <tr class="even"> <td>warning</td> <td>W0332</td> </tr> </table> </div> </div> </body> </html>'''.strip().splitlines() output = six.StringIO() linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('msg-template', '{category}{msg_id}') linter.open() linter.set_current_module('0123') linter.add_message('lowercase-l-suffix', line=1) linter.reporter.display_results(Section()) self.assertEqual(output.getvalue().splitlines(), expected)
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))
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_pylint_sees_all_non_underscore_symbols_for_trio_socket_in_namespace(): # Test pylints ast to contain the same content as dir(trio) from pylint.lint import PyLinter linter = PyLinter() ast_set = set(linter.get_ast(trio.socket.__file__, 'trio.socket')) trio_set = set([symbol for symbol in dir(trio.socket) if symbol[0] != '_']) assert trio_set - ast_set == set([])
def linter(): linter = PyLinter() linter.disable('I') linter.config.persistent = 0 # register checkers checkers.initialize(linter) linter.set_reporter(testutils.TestReporter()) return linter
def test_errors_only(linter: PyLinter) -> None: linter.error_mode() checkers = linter.prepare_checkers() checker_names = {c.name for c in checkers} should_not = { "design", "format", "metrics", "miscellaneous", "similarities" } assert set() == should_not & checker_names
def linter(): linter = PyLinter(reporter=TextReporter()) linter.disable('I') linter.config.persistent = 0 # register checkers checkers.initialize(linter) os.environ.pop('PYLINTRC', None) return linter
def linter(): linter = PyLinter() linter.set_reporter(InMemReporter()) checkers.initialize(linter) register(linter) linter.disable('all') linter.enable(SentryStackChecker.ADD_EXC_INFO) linter.enable(SentryStackChecker.CHANGE_TO_EXC_INFO) return linter
def test_addmessage(linter: PyLinter) -> None: linter.set_reporter(testutils.GenericTestReporter()) linter.open() linter.set_current_module("0123") linter.add_message("C0301", line=1, args=(1, 2)) linter.add_message("line-too-long", line=2, args=(3, 4)) assert [ "C: 1: Line too long (1/2)", "C: 2: Line too long (3/4)", ] == linter.reporter.messages
def initProject(path, script, prjFileName, classesPath): sys.path.append(path) global ropeProject global lint ropeProject = RopeProject.Project(path, fscommands=None, ropefolder=None, **ROPE_PREFS) ropeProject.validate() try: conf = createConfig(prjFileName) os.chdir(path) lint = PyLinter(pylintrc=conf, reporter=CheckReporter()) checkers.initialize(lint) lint.read_config_file() lint.load_config_file() lint.load_configuration() lint.quiet = 1 initImport(path, classesPath) # pydevd.settrace("localhost") except: sys.stderr.write(traceback.format_exc()) sys.stderr.flush() return True
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 #linter.load_default_plugins() 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)
def __init__(self, found_files, *args, **kwargs): self._files = found_files # set up the standard PyLint linter PyLinter.__init__(self, *args, **kwargs) # do some additional things! # for example, we want to re-initialise the OptionsManagerMixin # to supress the config error warning # pylint: disable=W0233 OptionsManagerMixIn.__init__(self, usage=PyLinter.__doc__, quiet=True)
def get_all_codes(cls): pylint = PyLinter() pylint.load_default_plugins() codes = [] for msg in pylint.msgs_store.messages: codes.append(( msg.symbol or msg.msgid, msg.msg.replace('\n', ' '), )) return codes
def __init__(self, ignore, rootpath, *args, **kwargs): self._ignore = ignore self._rootpath = rootpath # set up the standard PyLint linter PyLinter.__init__(self, *args, **kwargs) # do some additional things! # for example, we want to re-initialise the OptionsManagerMixin # to supress the config error warning # pylint: disable=W0233 OptionsManagerMixIn.__init__(self, usage=PyLinter.__doc__, quiet=True)
def builder_inited(app): # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/ base_path = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) linter = PyLinter() linter.load_default_plugins() features = os.path.join(base_path, 'doc', 'technical_reference', 'features.rst') with open(features, 'w') as stream: stream.write("Pylint features\n") stream.write("===============\n\n") stream.write(".. generated by pylint --full-documentation\n\n") linter.print_full_documentation(stream)
def builder_inited(app): # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/ base_path = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) linter = PyLinter() linter.load_default_plugins() features = os.path.join(base_path, "doc", "technical_reference", "features.rst") with open(features, "w") as stream: stream.write("Pylint features\n") stream.write("===============\n\n") stream.write(".. generated by pylint --full-documentation\n\n") print_full_documentation(linter, stream)
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 check_parallel( linter: PyLinter, jobs: int, files: Iterable[FileItem], arguments: None | str | Sequence[str] = None, ) -> None: """Use the given linter to lint the files with given amount of workers (jobs). This splits the work filestream-by-filestream. If you need to do work across multiple files, as in the similarity-checker, then implement the map/reduce mixin functionality. """ # The linter is inherited by all the pool's workers, i.e. the linter # is identical to the linter object here. This is required so that # a custom PyLinter object can be used. initializer = functools.partial(_worker_initialize, arguments=arguments) with multiprocessing.Pool( jobs, initializer=initializer, initargs=[dill.dumps(linter)] ) as pool: linter.open() all_stats = [] all_mapreduce_data: defaultdict[ int, list[defaultdict[str, list[Any]]] ] = defaultdict(list) # Maps each file to be worked on by a single _worker_check_single_file() call, # collecting any map/reduce data by checker module so that we can 'reduce' it # later. for ( worker_idx, # used to merge map/reduce data across workers module, file_path, base_name, messages, stats, msg_status, mapreduce_data, ) in pool.imap_unordered(_worker_check_single_file, files): linter.file_state.base_name = base_name linter.file_state._is_base_filestate = False linter.set_current_module(module, file_path) for msg in messages: linter.reporter.handle_message(msg) all_stats.append(stats) all_mapreduce_data[worker_idx].append(mapreduce_data) linter.msg_status |= msg_status pool.close() pool.join() _merge_mapreduce_data(linter, all_mapreduce_data) linter.stats = merge_stats([linter.stats] + all_stats)
def test_worker_initialize_pickling(self) -> None: """Test that we can pickle objects that standard pickling in multiprocessing can't. See: https://stackoverflow.com/questions/8804830/python-multiprocessing-picklingerror-cant-pickle-type-function https://github.com/PyCQA/pylint/pull/5584 """ linter = PyLinter(reporter=Reporter()) linter.attribute = argparse.ArgumentParser( ) # type: ignore[attr-defined] with multiprocessing.Pool(2, initializer=worker_initialize, initargs=[dill.dumps(linter)]) as pool: pool.imap_unordered(print, [1, 2])
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))
def linter(): linter = PyLinter() linter.set_reporter(MinimalTestReporter()) checkers.initialize(linter) linter.register_checker(MultipleTypesChecker(linter)) linter.disable('I') return linter
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
def test_simple_json_output(): output = StringIO() reporter = JSONReporter() linter = PyLinter(reporter=reporter) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.open() linter.set_current_module("0123") linter.add_message("line-too-long", line=1, args=(1, 2)) # we call this method because we didn't actually run the checkers reporter.display_messages(None) expected_result = [ [ ("column", 0), ("line", 1), ("message", "Line too long (1/2)"), ("message-id", "C0301"), ("module", "0123"), ("obj", ""), ("path", "0123"), ("symbol", "line-too-long"), ("type", "convention"), ] ] report_result = json.loads(output.getvalue()) report_result = [sorted(report_result[0].items(), key=lambda item: item[0])] assert report_result == expected_result
def linter(): linter = PyLinter() linter.set_reporter(MinimalTestReporter()) checkers.initialize(linter) linter.register_checker(OverlappingExceptionsChecker(linter)) linter.disable('I') return linter
def test_parseable_output_regression(self): output = six.StringIO() linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) self.assertMultiLineEqual( output.getvalue(), '************* Module 0123\n' '0123:1: [C0301(line-too-long), ] ' 'Line too long (1/2)\n')
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("suppressed-message") self._linter.disable("locally-disabled") self._linter.disable("useless-suppression") try: self._linter.read_config_file(test_file.option_file) self._linter.load_config_file() except NoFileError: pass self._test_file = test_file
def linter(): linter = PyLinter() linter.set_reporter(MinimalTestReporter()) checkers.initialize(linter) register(linter) linter.disable('all') linter.enable('too-complex') return linter
def test_parseable_output_regression(): output = StringIO() with warnings.catch_warnings(record=True): linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option("output-format", "parseable") linter.open() linter.set_current_module("0123") linter.add_message("line-too-long", line=1, args=(1, 2)) assert (output.getvalue() == "************* Module 0123\n" "0123:1: [C0301(line-too-long), ] " "Line too long (1/2)\n")
def builder_inited(app: Optional[Sphinx]) -> None: """Output full documentation in ReST format for all extension modules.""" # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/ base_path = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # PACKAGE/ --> PACKAGE/pylint/extensions ext_path = os.path.join(base_path, "pylint", "extensions") modules = [] doc_files = {} for filename in os.listdir(ext_path): name, ext = os.path.splitext(filename) if name[0] == "_": continue if ext == ".py": modules.append(f"pylint.extensions.{name}") elif ext == ".rst": doc_files["pylint.extensions." + name] = os.path.join( ext_path, filename) modules.sort() if not modules: sys.exit("No Pylint extensions found?") linter = PyLinter() linter.load_plugin_modules(modules) extensions_doc = os.path.join(base_path, "doc", "technical_reference", "extensions.rst") with open(extensions_doc, "w", encoding="utf-8") as stream: stream.write( get_rst_title("Optional Pylint checkers in the extensions module", "=")) stream.write("Pylint provides the following optional plugins:\n\n") for module in modules: stream.write(f"- :ref:`{module}`\n") stream.write("\n") stream.write("You can activate any or all of these extensions " "by adding a ``load-plugins`` line to the ``MASTER`` " "section of your ``.pylintrc``, for example::\n") stream.write("\n load-plugins=pylint.extensions.docparams," "pylint.extensions.docstyle\n\n") # Print checker documentation to stream by_checker = get_plugins_info(linter, doc_files) for checker, information in sorted(by_checker.items()): checker = information["checker"] del information["checker"] print(checker.get_full_documentation(**information)[:-1], file=stream)
def expand_files(self, modules): expanded = PyLinter.expand_files(self, modules) filtered = [] for module in expanded: if self._files.check_module(module['path']): filtered.append(module) return filtered
def test_parseable_output_regression(): output = six.StringIO() with warnings.catch_warnings(record=True): linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) assert output.getvalue() == \ '************* Module 0123\n' \ '0123:1: [C0301(line-too-long), ] ' \ 'Line too long (1/2)\n'
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 expand_files(self, modules): expanded = PyLinter.expand_files(self, modules) filtered = [] for module in expanded: if any([m.search(module['path']) for m in self._ignore]): continue filtered.append(module) return filtered
def linter(): linter = PyLinter() linter.set_reporter(MinimalTestReporter()) checkers.initialize(linter) linter.register_checker(BadBuiltinChecker(linter)) linter.disable('I') return linter
def test_parseable_output_regression(self): output = six.StringIO() linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) self.assertMultiLineEqual(output.getvalue(), '************* Module 0123\n' '0123:1: [C0301(line-too-long), ] ' 'Line too long (1/2)\n')
def expand_files(self, modules): expanded = PyLinter.expand_files(self, modules) filtered = [] for module in expanded: rel_path = os.path.relpath(module['path'], self._rootpath) if any([m.search(rel_path) for m in self._ignore]): continue filtered.append(module) return filtered
def linter(checker, register, enable, disable, reporter): _linter = PyLinter() _linter.set_reporter(reporter()) checkers.initialize(_linter) if register: register(_linter) if checker: _linter.register_checker(checker(_linter)) if disable: for msg in disable: _linter.disable(msg) if enable: for msg in enable: _linter.enable(msg) os.environ.pop("PYLINTRC", None) return _linter
def test_parseable_output_regression(): output = StringIO() with warnings.catch_warnings(record=True): linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) assert output.getvalue() == \ '************* Module 0123\n' \ '0123:1: [C0301(line-too-long), ] ' \ 'Line too long (1/2)\n'
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 builder_inited(app): """Output full documentation in ReST format for all extension modules""" # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/ base_path = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # PACKAGE/ --> PACKAGE/pylint/extensions ext_path = os.path.join(base_path, 'pylint', 'extensions') modules = [] doc_files = {} for filename in os.listdir(ext_path): name, ext = os.path.splitext(filename) if name[0] == '_' or name in DEPRECATED_MODULES: continue if ext == '.py': modules.append('pylint.extensions.%s' % name) elif ext == '.rst': doc_files['pylint.extensions.' + name] = os.path.join(ext_path, filename) modules.sort() if not modules: sys.exit("No Pylint extensions found?") linter = PyLinter() linter.load_plugin_modules(modules) extensions_doc = os.path.join(base_path, 'doc', 'technical_reference', 'extensions.rst') with open(extensions_doc, 'w') as stream: stream.write("Optional Pylint checkers in the extensions module\n") stream.write("=================================================\n\n") stream.write("Pylint provides the following optional plugins:\n\n") for module in modules: stream.write("- :ref:`{0}`\n".format(module)) stream.write("\n") stream.write("You can activate any or all of these extensions " "by adding a ``load-plugins`` line to the ``MASTER`` " "section of your ``.pylintrc``, for example::\n") stream.write("\n load-plugins=pylint.extensions.docparams," "pylint.extensions.docstyle\n\n") by_module = get_plugins_info(linter, doc_files) for module, info in sorted(six.iteritems(by_module)): linter._print_checker_doc(info['name'], info, stream=stream)
def test_html_reporter_type(self): # Integration test for issue #263 # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems expected = '''<html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>type</th> <th>module</th> <th>object</th> <th>line</th> <th>col_offset</th> <th>message</th> </tr> <tr class="even"> <td>convention</td> <td>0123</td> <td> </td> <td>1</td> <td>0</td> <td>Exactly one space required before comparison a< 5: print "zero"</td> </tr> </table> </div> </div> </body> </html> ''' output = six.StringIO() with testutils.catch_warnings(): linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.open() linter.set_current_module('0123') linter.add_message('bad-whitespace', line=1, args=('Exactly one', 'required', 'before', 'comparison', 'a< 5: print "zero"')) linter.reporter.display_reports(Section()) self.assertMultiLineEqual(output.getvalue(), expected)
to be incorporated in the automatic functional test framework """ import sys import os from os.path import abspath, dirname, join from logilab.common.testlib import TestCase, unittest_main from utils import TestReporter from pylint.lint import PyLinter from pylint import checkers test_reporter = TestReporter() linter = PyLinter() linter.set_reporter(test_reporter) linter.disable('I') linter.config.persistent = 0 checkers.initialize(linter) REGR_DATA = join(dirname(abspath(__file__)), 'regrtest_data') sys.path.insert(1, REGR_DATA) class NonRegrTC(TestCase): def setUp(self): """call reporter.finalize() to cleanup pending messages if a test finished badly """ linter.reporter.finalize()
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)
class PyLinterTC(unittest.TestCase): def setUp(self): self.linter = PyLinter(reporter=TextReporter()) self.linter.disable('I') self.linter.config.persistent = 0 # register checkers checkers.initialize(self.linter) os.environ.pop('PYLINTRC', None) def test_add_message_is_deprecated(self): if __pkginfo__.numversion >= (1, 6, 0): with self.assertRaises(AttributeError): BaseReporter().add_message with warnings.catch_warnings(record=True) as cm: warnings.simplefilter("always") BaseReporter().add_message(None, None, None) self.assertEqual(len(cm), 1) self.assertIsInstance(cm[0].message, DeprecationWarning) msg = ('This method is deprecated, use handle_message ' 'instead. It will be removed in Pylint 1.6.') self.assertEqual(str(cm[0].message), msg) def test_template_option(self): output = six.StringIO() self.linter.reporter.set_output(output) self.linter.set_option('msg-template', '{msg_id}:{line:03d}') self.linter.open() self.linter.set_current_module('0123') self.linter.add_message('C0301', line=1, args=(1, 2)) self.linter.add_message('line-too-long', line=2, args=(3, 4)) self.assertMultiLineEqual(output.getvalue(), '************* Module 0123\n' 'C0301:001\n' 'C0301:002\n') def test_parseable_output_deprecated(self): with warnings.catch_warnings(record=True) as cm: warnings.simplefilter("always") ParseableTextReporter() self.assertEqual(len(cm), 1) self.assertIsInstance(cm[0].message, DeprecationWarning) def test_parseable_output_regression(self): output = six.StringIO() with warnings.catch_warnings(record=True): linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) self.assertMultiLineEqual(output.getvalue(), '************* Module 0123\n' '0123:1: [C0301(line-too-long), ] ' 'Line too long (1/2)\n') def test_html_reporter_msg_template(self): expected = ''' <html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>category</th> <th>msg_id</th> </tr> <tr class="even"> <td>warning</td> <td>W0332</td> </tr> </table> </div> </div> </body> </html>'''.strip().splitlines() output = six.StringIO() linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('msg-template', '{category}{msg_id}') linter.open() linter.set_current_module('0123') linter.add_message('lowercase-l-suffix', line=1) linter.reporter.display_results(Section()) self.assertEqual(output.getvalue().splitlines(), expected) @unittest.expectedFailure def test_html_reporter_type(self): # Integration test for issue #263 # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems expected = '''<html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>type</th> <th>module</th> <th>object</th> <th>line</th> <th>col_offset</th> <th>message</th> </tr> <tr class="even"> <td>convention</td> <td>0123</td> <td> </td> <td>1</td> <td>0</td> <td>Exactly one space required before comparison a< 5: print "zero"</td> </tr> </table> </div> </div> </body> </html> ''' output = six.StringIO() linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.open() linter.set_current_module('0123') linter.add_message('bad-whitespace', line=1, args=('Exactly one', 'required', 'before', 'comparison', 'a< 5: print "zero"')) linter.reporter.display_results(Section()) self.assertMultiLineEqual(output.getvalue(), expected)
The list of messages must exactly match *all* the messages added by the method. Additionally, we check to see whether the args in each message can actually be substituted into the message string. """ yield got = self.linter.release_messages() msg = ('Expected messages did not match actual.\n' 'Expected:\n%s\nGot:\n%s' % ('\n'.join(repr(m) for m in messages), '\n'.join(repr(m) for m in got))) self.assertEqual(got, list(messages), msg) # Init test_reporter = TestReporter() linter = PyLinter() linter.set_reporter(test_reporter) linter.config.persistent = 0 checkers.initialize(linter) linter.global_set_option('required-attributes', ('__revision__',)) if linesep != '\n': LINE_RGX = re.compile(linesep) def ulines(string): return LINE_RGX.sub('\n', string) else: def ulines(string): return string INFO_TEST_RGX = re.compile(r'^func_i\d\d\d\d$')
class PyLinterTC(unittest.TestCase): def setUp(self): self.linter = PyLinter(reporter=TextReporter()) self.linter.disable('I') self.linter.config.persistent = 0 # register checkers checkers.initialize(self.linter) os.environ.pop('PYLINTRC', None) def test_template_option(self): output = six.StringIO() self.linter.reporter.set_output(output) self.linter.set_option('msg-template', '{msg_id}:{line:03d}') self.linter.open() self.linter.set_current_module('0123') self.linter.add_message('C0301', line=1, args=(1, 2)) self.linter.add_message('line-too-long', line=2, args=(3, 4)) self.assertMultiLineEqual(output.getvalue(), '************* Module 0123\n' 'C0301:001\n' 'C0301:002\n') def test_parseable_output_deprecated(self): with warnings.catch_warnings(record=True) as cm: warnings.simplefilter("always") ParseableTextReporter() self.assertEqual(len(cm), 1) self.assertIsInstance(cm[0].message, DeprecationWarning) def test_parseable_output_regression(self): output = six.StringIO() with warnings.catch_warnings(record=True): linter = PyLinter(reporter=ParseableTextReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('output-format', 'parseable') linter.open() linter.set_current_module('0123') linter.add_message('line-too-long', line=1, args=(1, 2)) self.assertMultiLineEqual(output.getvalue(), '************* Module 0123\n' '0123:1: [C0301(line-too-long), ] ' 'Line too long (1/2)\n') def test_display_results_is_renamed(self): class CustomReporter(TextReporter): def _display(self, layout): return None reporter = CustomReporter() with self.assertRaises(AttributeError): reporter.display_results
import unittest import sys import re import new from os import linesep from os.path import exists from logilab.common import testlib from utils import get_tests_info, fix_path, TestReporter from pylint.lint import PyLinter from pylint import checkers test_reporter = TestReporter() linter = PyLinter() linter.set_reporter(test_reporter) linter.config.persistent = 0 checkers.initialize(linter) linter.enable_checkers(['rpython'], True) from test_func import ulines, LintTestUsingFile class RLintTestUsingFile(LintTestUsingFile): package = 'rpythoninput' linter = linter def setUp(self): if sys.version_info[:2] != (2, 4): self.skip('only python 2.4 supported for now') def test_functionality(self):