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 lint_py_files_for_python3_compatibility(self): """Prints a list of Python 3 compatibility errors in the given list of Python files. Returns: TaskResult. A TaskResult object representing the result of the lint check. """ files_to_lint = self.all_filepaths any_errors = False error_messages = [] full_error_messages = [] name = 'Pylint for Python 3 compatibility' files_to_lint_for_python3_compatibility = [ file_name for file_name in files_to_lint if not re.match(r'^.*python_utils.*\.py$', file_name) ] if not files_to_lint_for_python3_compatibility: return [ concurrent_task_utils.TaskResult(name, False, [], [ 'There are no Python files to lint for Python 3 ' 'compatibility.' ]) ] _batch_size = 50 current_batch_start_index = 0 while current_batch_start_index < len( files_to_lint_for_python3_compatibility): # Note that this index is an exclusive upper bound -- i.e., # the current batch of files ranges from 'start_index' to # 'end_index - 1'. current_batch_end_index = min( current_batch_start_index + _batch_size, len(files_to_lint_for_python3_compatibility)) current_files_to_lint = files_to_lint_for_python3_compatibility[ current_batch_start_index:current_batch_end_index] pylint_report = python_utils.string_io() pylinter_for_python3 = lint.Run( current_files_to_lint + ['--py3k'], reporter=text.TextReporter(pylint_report), exit=False).linter if pylinter_for_python3.msg_status != 0: lint_message = pylint_report.getvalue() pylint_error_messages = ( self.get_trimmed_error_output(lint_message)) error_messages.append(pylint_error_messages) full_error_messages.append('Messages for Python 3 support:') full_error_messages.append(lint_message) any_errors = True current_batch_start_index = current_batch_end_index return concurrent_task_utils.TaskResult(name, any_errors, error_messages, full_error_messages)
def run_pylint(filename, rcfile=None): """run pylint check.""" disable = ["E1103", # maybe-no-member "W0142", # star-args "W1201", # logging-not-lazy "I0011", # locally-disabled "I0012", # locally-enabled "R0801", # duplicate-code "R0901", # too-many-ancestors "R0902", # too-many-instance-attributes "R0903", # too-few-public-methods "R0904", # too-many-public-methods "R0921", # abstract-class-not-used "R0922"] # abstract-class-little-used enable = ["W0511"] # fixme args = [ "-r", "n", "--persistent=n", "-d", ",".join(disable), "-e", ",".join(enable)] if rcfile: args.append("--rcfile=%s" % rcfile) kwargs = dict(exit=False) try: kwargs['reporter'] = text.TextReporter(sys.stdout) kwargs['reporter'].line_format # pylint: disable=pointless-statement args += ["--msg-template", "{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}"] except AttributeError: kwargs['reporter'] = text.ParseableTextReporter(sys.stdout) args += ["-f", "parseable", "-i", "y"] lint.Run(args + [filename], **kwargs)
def test_pylint(self): stdout = StringIO() reporter = text.TextReporter(stdout) opts = ["--score=no", "chatwatch"] pylint.Run(opts, reporter=reporter, do_exit=False) out = reporter.out.getvalue() failed = bool(out) assert not failed, "Pylint found violations"
def run(config, *args): """ Run pylint """ try: from pylint import lint from pylint.reporters import text except ImportError: return 2 if config is None: config = _shell.native('pylintrc') argv = [ '--rcfile', config, '--reports', 'no', ] stream = FilterStream(_term.terminfo()) old_stderr = _sys.stderr try: # pylint: disable = E1101 _sys.stderr = stream from pylint import __pkginfo__ if __pkginfo__.numversion >= (1, 0, 0): reporter = text.TextReporter(stream) argv.extend([ '--msg-template', '{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}' ]) else: argv.extend( ['--output-format', 'parseable', '--include-ids', 'yes']) if __pkginfo__.numversion < (0, 13): lint.REPORTER_OPT_MAP['parseable'] = \ lambda: text.TextReporter2(stream) reporter = text.TextReporter2(stream) else: reporter = text.ParseableTextReporter(stream) lint.REPORTER_OPT_MAP['parseable'] = lambda: reporter for path in args: try: try: lint.Run(argv + [path], reporter=reporter) except SystemExit: pass # don't accept the exit. strange errors happen... if stream.written: print() stream.written = False except KeyboardInterrupt: print() raise finally: _sys.stderr = old_stderr return 0
def run_pylint(): buff = six.StringIO() reporter = text.TextReporter(output=buff) args = [ "--msg-template='{path}:{line}: [{msg_id}i({symbol}), {obj}] {msg}'", "-E", "manila"] lint.Run(args, reporter=reporter, exit=False) val = buff.getvalue() buff.close() return val
def run_pylint(): buff = StringIO() reporter = text.TextReporter(output=buff) args = [ "--msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'", "-j", "%s" % multiprocessing.cpu_count(), "-E", "cinder" ] lint.Run(args, reporter=reporter, exit=False) val = buff.getvalue() buff.close() return val
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"])
def test_pylint_visit_method_taken_in_account(linter): 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")
def test_pylint(): stdout = StringIO() reporter = text.TextReporter(stdout) opts = ['--max-line-length=150', '--score=no', '--disable=missing-docstring, wildcard-import, ' 'attribute-defined-outside-init, too-few-public-methods, ' 'old-style-class,import-error,invalid-name,no-init,' 'too-many-instance-attributes,protected-access,too-many-arguments,' 'too-many-public-methods,logging-format-interpolation,' 'too-many-branches', 'ksoftapi'] pylint.Run(opts, reporter=reporter, do_exit=False) out = reporter.out.getvalue() failed = bool(out) return failed
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_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_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
__implements__ = interfaces.IAstroidChecker msgs = { 'R9991': ( "Consider Using %s.extend(%s)", "consider-using-extend", "Consider using list.extend instead of '+=' " "will allow you to use", ), } def visit_augassign(self, node): try: for inferred in node.target.infer(): if inferred.qname() == 'builtins.list': args = (node.target.name, node.value.as_string()) self.add_message('consider-using-extend', node=node, args=args) except astroid.InferenceError: pass linter = lint.PyLinter() linter.register_checker(MyChecker(linter)) args = linter.load_command_line_configuration() linter.set_reporter(text.TextReporter()) linter.disable('bad-option-value') with lint.fix_import_path(args): linter.check(args) linter.generate_reports()
def lint_py_files(self): """Prints a list of lint errors in the given list of Python files. Returns: TaskResult. A TaskResult object representing the result of the lint check. """ pylintrc_path = os.path.join(os.getcwd(), '.pylintrc') config_pylint = '--rcfile=%s' % pylintrc_path config_pycodestyle = os.path.join(os.getcwd(), 'tox.ini') files_to_lint = self.all_filepaths errors_found = False error_messages = [] full_error_messages = [] name = 'Pylint' _batch_size = 50 current_batch_start_index = 0 stdout = io.StringIO() while current_batch_start_index < len(files_to_lint): # Note that this index is an exclusive upper bound -- i.e., # the current batch of files ranges from 'start_index' to # 'end_index - 1'. current_batch_end_index = min( current_batch_start_index + _batch_size, len(files_to_lint)) current_files_to_lint = files_to_lint[ current_batch_start_index:current_batch_end_index] pylint_report = io.StringIO() pylinter = lint.Run(current_files_to_lint + [config_pylint], reporter=text.TextReporter(pylint_report), exit=False).linter if pylinter.msg_status != 0: lint_message = pylint_report.getvalue() full_error_messages.append(lint_message) pylint_error_messages = ( self.get_trimmed_error_output(lint_message)) error_messages.append(pylint_error_messages) errors_found = True with linter_utils.redirect_stdout(stdout): # These lines invoke Pycodestyle and print its output # to the target stdout. style_guide = pycodestyle.StyleGuide( config_file=config_pycodestyle) pycodestyle_report = style_guide.check_files( paths=current_files_to_lint) if pycodestyle_report.get_count() != 0: error_message = stdout.getvalue() full_error_messages.append(error_message) error_messages.append(error_message) errors_found = True current_batch_start_index = current_batch_end_index return concurrent_task_utils.TaskResult(name, errors_found, error_messages, full_error_messages)
def _lint_py_files_for_python3_compatibility(self): """Prints a list of Python 3 compatibility errors in the given list of Python files. Returns: summary_messages: list(str). Summary of lint check. """ files_to_lint = self.all_filepaths start_time = time.time() any_errors = False stdout = python_utils.string_io() summary_messages = [] files_to_lint_for_python3_compatibility = [ file_name for file_name in files_to_lint if not re.match(r'^.*python_utils.*\.py$', file_name) ] num_py_files = len(files_to_lint_for_python3_compatibility) if not files_to_lint_for_python3_compatibility: python_utils.PRINT('') python_utils.PRINT( 'There are no Python files to lint for Python 3 compatibility.' ) return [] python_utils.PRINT( 'Linting %s Python files for Python 3 compatibility.' % (num_py_files)) _batch_size = 50 current_batch_start_index = 0 while current_batch_start_index < len( files_to_lint_for_python3_compatibility): # Note that this index is an exclusive upper bound -- i.e., # the current batch of files ranges from 'start_index' to # 'end_index - 1'. current_batch_end_index = min( current_batch_start_index + _batch_size, len(files_to_lint_for_python3_compatibility)) current_files_to_lint = files_to_lint_for_python3_compatibility[ current_batch_start_index:current_batch_end_index] if self.verbose_mode_enabled: python_utils.PRINT( 'Linting Python files for Python 3 compatibility %s to %s..' % (current_batch_start_index + 1, current_batch_end_index)) with linter_utils.redirect_stdout(stdout): # This line invokes Pylint and prints its output # to the target stdout. python_utils.PRINT('Messages for Python 3 support:') pylint_report = StringMessageStream() pylinter_for_python3 = lint.Run( current_files_to_lint + ['--py3k'], reporter=text.TextReporter(pylint_report), exit=False).linter if pylinter_for_python3.msg_status != 0: summary_message = stdout.getvalue() pylint_error_messages = (self._get_trimmed_error_output( pylint_report.read())) summary_messages.append(pylint_error_messages) for message in pylint_report.read(): python_utils.PRINT(message) any_errors = True current_batch_start_index = current_batch_end_index if any_errors: summary_message = ( '%s Python linting for Python 3 compatibility failed' % linter_utils.FAILED_MESSAGE_PREFIX) else: summary_message = ( '%s %s Python files linted for Python 3 compatibility ' '(%.1f secs)' % (linter_utils.SUCCESS_MESSAGE_PREFIX, num_py_files, (time.time() - start_time))) python_utils.PRINT(summary_message) summary_messages.append(summary_message) python_utils.PRINT( 'Python linting for Python 3 compatibility finished.') return summary_messages
def _lint_py_files(self, config_pylint, config_pycodestyle): """Prints a list of lint errors in the given list of Python files. Args: config_pylint: str. Path to the .pylintrc file. config_pycodestyle: str. Path to the tox.ini file. Returns: summary_messages: list(str). Summary messages of lint check. """ files_to_lint = self.all_filepaths start_time = time.time() are_there_errors = False summary_messages = [] num_py_files = len(files_to_lint) python_utils.PRINT('Linting %s Python files' % num_py_files) _batch_size = 50 current_batch_start_index = 0 stdout = python_utils.string_io() while current_batch_start_index < len(files_to_lint): # Note that this index is an exclusive upper bound -- i.e., # the current batch of files ranges from 'start_index' to # 'end_index - 1'. current_batch_end_index = min( current_batch_start_index + _batch_size, len(files_to_lint)) current_files_to_lint = files_to_lint[ current_batch_start_index:current_batch_end_index] if self.verbose_mode_enabled: python_utils.PRINT( 'Linting Python files %s to %s...' % (current_batch_start_index + 1, current_batch_end_index)) with linter_utils.redirect_stdout(stdout): # This line invokes Pylint and prints its output # to the target stdout. pylint_report = StringMessageStream() pylinter = lint.Run(current_files_to_lint + [config_pylint], reporter=text.TextReporter(pylint_report), exit=False).linter # These lines invoke Pycodestyle and print its output # to the target stdout. style_guide = pycodestyle.StyleGuide( config_file=config_pycodestyle) pycodestyle_report = style_guide.check_files( paths=current_files_to_lint) if pylinter.msg_status != 0 or pycodestyle_report.get_count() != 0: summary_message = stdout.getvalue() for message in pylint_report.read(): python_utils.PRINT(message) pylint_error_messages = (self._get_trimmed_error_output( pylint_report.read())) summary_messages.append(pylint_error_messages) python_utils.PRINT(summary_message) are_there_errors = True current_batch_start_index = current_batch_end_index if are_there_errors: summary_message = ('%s Python linting failed' % (linter_utils.FAILED_MESSAGE_PREFIX)) else: summary_message = ('%s %s Python files linted (%.1f secs)' % (linter_utils.SUCCESS_MESSAGE_PREFIX, num_py_files, time.time() - start_time)) python_utils.PRINT(summary_message) summary_messages.append(summary_message) python_utils.PRINT('Python linting finished.') return summary_messages
def main(): usage = """ %prog [options] target Django Lint is a tool that statically analyses Django projects and applications, checking for programming errors and bad code smells. For example, it reports nullable "CharField" fields, as well as reporting for unspecified options in settings.py. The `target` argument is mandatory and can specify either a directory containing a Django project, a single application or a single file. """.rstrip() parser = OptionParser(usage=usage) parser.add_option( '-r', '--reports', dest='report', action='store_true', default=False, help='generate report', ) parser.add_option( '-p', '--pylint', dest='pylint', action='store_true', default=False, help='run normal PyLint checks', ) parser.add_option( '-e', '--errors', dest='errors', action='store_true', default=False, help='only show errors', ) parser.add_option( '-f', '--format', dest='outputformat', metavar='OUTPUT', default='text', help='Set the output format. Available formats are text,' 'parseable, colorized, msvs (visual studio) and html', ) options, args = parser.parse_args() try: args[0] except IndexError: args = ['.'] targets = [os.path.abspath(arg) for arg in args] for target in targets: if not os.path.exists(target): try: # Is target a module? x = __import__(args[0], locals(), globals(), [], -1) target = sys.modules[args[0]].__path__[0] except: pass if not os.path.exists(target): raise parser.error( "The specified target (%r) does not exist" \ % target ) path = target while True: flag = False for django_file in ('manage.py', 'models.py', 'urls.py'): if os.path.exists(os.path.join(path, django_file)): sys.path.insert(0, os.path.dirname(path)) flag = True break if flag: break path = os.path.dirname(path) if path == '/': raise parser.error( "The specified target (%r) does not appear to be part of a " \ "Django application" % target ) try: import django except ImportError: print >>sys.stderr, "E: Cannot import `django' module, exiting.." return 1 linter = lint.PyLinter() linter.set_reporter(text_reporter.TextReporter()) linter.set_option('reports', options.report) linter.set_option('output-format', options.outputformat) if options.pylint: checkers.initialize(linter) for msg in ('C0111', 'C0301'): linter.disable(msg) AstCheckers.register(linter) if options.errors: linter.set_option('disable-msg-cat', 'WCRI') linter.set_option('reports', False) linter.set_option('persistent', False) linter.check(targets) return linter.msg_status