Skip to content

Commit a9444d8

Browse files
committed
PyLinter is no longer a reports handler
1 parent 08a5c6d commit a9444d8

File tree

2 files changed

+79
-74
lines changed

2 files changed

+79
-74
lines changed

pylint/lint.py

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ def report_messages_by_module_stats(sect, stats, _):
238238

239239
# pylint: disable=too-many-instance-attributes
240240
class PyLinter(utils.MessagesHandlerMixIn,
241-
utils.ReportsHandlerMixIn,
242241
checkers.BaseTokenChecker):
243242
"""lint Python modules using external checkers.
244243
@@ -416,7 +415,6 @@ def __init__(self, config=None):
416415
# visit variables
417416
self.current_name = None
418417
self.current_file = None
419-
self.stats = None
420418

421419
# TODO: Runner needs to give this to parser?
422420
full_version = '%%prog %s\nastroid %s\nPython %s' % (
@@ -439,12 +437,6 @@ def disable_noerror_messages(self):
439437
for msgid in msgids:
440438
self.disable(msgid)
441439

442-
def disable_reporters(self):
443-
"""disable all reporters"""
444-
for _reporters in six.itervalues(self._reports):
445-
for report_id, _, _ in _reporters:
446-
self.disable_report(report_id)
447-
448440
def error_mode(self):
449441
"""error mode: enable only errors; no reports, no persistent"""
450442
self._error_mode = True
@@ -546,29 +538,6 @@ def process_tokens(self, tokens):
546538

547539
# code checking methods ###################################################
548540

549-
def get_checkers(self):
550-
"""return all available checkers as a list"""
551-
return [self] + [c for _checkers in six.itervalues(self._checkers)
552-
for c in _checkers if c is not self]
553-
554-
def prepare_checkers(self):
555-
"""return checkers needed for activated messages and reports"""
556-
if not self.config.reports:
557-
self.disable_reporters()
558-
# get needed checkers
559-
neededcheckers = [self]
560-
for checker in self.get_checkers()[1:]:
561-
messages = set(msg for msg in checker.msgs
562-
if self.is_message_enabled(msg))
563-
if (messages or
564-
any(self.report_is_enabled(r[0]) for r in checker.reports)):
565-
neededcheckers.append(checker)
566-
# Sort checkers by priority
567-
neededcheckers = sorted(neededcheckers,
568-
key=operator.attrgetter('priority'),
569-
reverse=True)
570-
return neededcheckers
571-
572541
# pylint: disable=unused-argument
573542
@staticmethod
574543
def should_analyze_file(modname, path, is_argument=False):
@@ -598,7 +567,7 @@ def _init_msg_states(self):
598567
if not msg.may_be_emitted():
599568
self._msgs_state[msg.msgid] = False
600569

601-
def check(self, files_or_modules):
570+
def check(self, files_or_modules, checkers_):
602571
"""main checking entry: check a list of files or modules from their
603572
name.
604573
"""
@@ -609,18 +578,17 @@ def check(self, files_or_modules):
609578
if not isinstance(files_or_modules, (list, tuple)):
610579
files_or_modules = (files_or_modules,)
611580

612-
self._do_check(files_or_modules)
581+
self._do_check(files_or_modules, checkers_)
613582

614-
def _do_check(self, files_or_modules):
583+
def _do_check(self, files_or_modules, checkers_):
615584
walker = utils.PyLintASTWalker(self)
616-
_checkers = self.prepare_checkers()
617-
tokencheckers = [c for c in _checkers
585+
tokencheckers = [c for c in checkers_
618586
if interfaces.implements(c, interfaces.ITokenChecker)
619587
and c is not self]
620-
rawcheckers = [c for c in _checkers
588+
rawcheckers = [c for c in checkers_
621589
if interfaces.implements(c, interfaces.IRawChecker)]
622590
# notify global begin
623-
for checker in _checkers:
591+
for checker in checkers_:
624592
checker.open()
625593
if interfaces.implements(checker, interfaces.IAstroidChecker):
626594
walker.add_checker(checker)
@@ -657,7 +625,7 @@ def _do_check(self, files_or_modules):
657625
self.add_message(msgid, line, None, args)
658626
# notify global end
659627
self.stats['statement'] = walker.nbstatements
660-
for checker in reversed(_checkers):
628+
for checker in reversed(checkers_):
661629
checker.close()
662630

663631
def set_current_module(self, modname, filepath=None):
@@ -723,9 +691,10 @@ def check_astroid_module(self, ast_node, walker,
723691

724692
def open(self):
725693
"""initialize counters"""
726-
self.stats = {'by_module' : {},
727-
'by_msg' : {},
728-
}
694+
self.stats = {
695+
'by_module': {},
696+
'by_msg': {},
697+
}
729698
MANAGER.always_load_extensions = self.config.unsafe_load_any_extension
730699
MANAGER.extension_package_whitelist.update(
731700
self.config.extension_pkg_whitelist)
@@ -778,8 +747,9 @@ def guess_lint_path(args):
778747

779748
return value
780749

781-
782-
class PluginRegistry(object):
750+
# TODO: Split the ReportsHandlerMixIn, keeping register methods here,
751+
# and moving report_order and make_reports to the runner.
752+
class PluginRegistry(utils.ReportsHandlerMixIn):
783753
"""A class to register checkers to."""
784754

785755
def __init__(self, linter, register_options=(lambda options: None)):
@@ -789,12 +759,10 @@ def __init__(self, linter, register_options=(lambda options: None)):
789759
# TODO: Remove. This is needed for the MessagesHandlerMixIn for now.
790760
linter._checkers = self._checkers
791761
self._reporters = {}
792-
linter._reporters = self._reporters
793762
self._linter = linter
794763

795-
# TODO: Move elsewhere
796764
for r_id, r_title, r_cb in linter.reports:
797-
self._linter.register_post_report(r_id, r_title, r_cb)
765+
self.register_post_report(r_id, r_title, r_cb)
798766

799767
self.register_options(linter.options)
800768

@@ -825,9 +793,8 @@ def register_checker(self, checker):
825793

826794
self._checkers[checker.name].append(checker)
827795

828-
# TODO: Move elsewhere
829796
for r_id, r_title, r_cb in checker.reports:
830-
self._linter.register_report(r_id, r_title, r_cb, checker)
797+
self.register_report(r_id, r_title, r_cb, checker)
831798

832799
self.register_options(checker.options)
833800

@@ -850,7 +817,7 @@ def register_reporter(self, reporter_class):
850817

851818
self._reporters[reporter_class.name] = reporter_class
852819

853-
# For now simply defer missing attributs to the linter,
820+
# For now simply defer missing attributes to the linter,
854821
# until we know what API we want.
855822
def __getattr__(self, attribute):
856823
return getattr(self._linter, attribute)
@@ -943,7 +910,7 @@ class CLIRunner(Runner):
943910
)
944911

945912
def __init__(self):
946-
super(CLIRunner, self).__init__()
913+
super().__init__()
947914
self._linter = PyLinter()
948915
self._plugin_registry = PluginRegistry(self._linter)
949916
self._loaded_plugins = set()
@@ -1074,9 +1041,14 @@ def register_options(options):
10741041
for checker in self._plugin_registry.for_all_checkers():
10751042
checker.config = self._global_config
10761043

1044+
if not self._global_config.reports:
1045+
self._plugin_registry.disable_reporters()
1046+
10771047
with fix_import_path(self._global_config.module_or_package):
10781048
assert self._global_config.jobs == 1
1079-
self._linter.check(self._global_config.module_or_package)
1049+
self._linter.check(
1050+
self._global_config.module_or_package, self.prepare_checkers(),
1051+
)
10801052

10811053
self.generate_reports()
10821054

@@ -1147,7 +1119,8 @@ def generate_reports(self):
11471119
# XXX code below needs refactoring to be more reporter agnostic
11481120
self._reporter.on_close(self._linter.stats, previous_stats)
11491121
if self._global_config.reports:
1150-
sect = self._linter.make_reports(self._linter.stats, previous_stats)
1122+
# TODO: The Runner should make reports, not the registry.
1123+
sect = self._plugin_registry.make_reports(self._linter.stats, previous_stats)
11511124
else:
11521125
sect = report_nodes.Section()
11531126

@@ -1185,6 +1158,28 @@ def _report_evaluation(self):
11851158
sect = report_nodes.EvaluationSection(msg)
11861159
self._reporter.display_reports(sect)
11871160

1161+
def get_checkers(self):
1162+
"""return all available checkers as a list"""
1163+
return [self._linter] + [
1164+
c for c in self._plugin_registry.for_all_checkers() if c is not self._linter
1165+
]
1166+
1167+
def prepare_checkers(self):
1168+
"""return checkers needed for activated messages and reports"""
1169+
# get needed checkers
1170+
neededcheckers = [self._linter]
1171+
for checker in self.get_checkers()[1:]:
1172+
messages = set(msg for msg in checker.msgs
1173+
if self._linter.is_message_enabled(msg))
1174+
if (messages or
1175+
any(self._plugin_registry.report_is_enabled(r[0]) for r in checker.reports)):
1176+
neededcheckers.append(checker)
1177+
# Sort checkers by priority
1178+
neededcheckers = sorted(neededcheckers,
1179+
key=operator.attrgetter('priority'),
1180+
reverse=True)
1181+
return neededcheckers
1182+
11881183

11891184
if __name__ == '__main__':
11901185
CLIRunner().run(sys.argv[1:])

pylint/utils.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ def __init__(self):
256256
self.msg_status = 0
257257
self.msgs_store = MessagesStore()
258258
self.reporter = None
259+
self.stats = {
260+
'by_module': {},
261+
'by_msg': {},
262+
}
259263
super().__init__()
260264

261265
def _checker_messages(self, checker):
@@ -300,13 +304,7 @@ def _set_msg_status(self, msgid, enable, scope='package', line=None, ignore_unkn
300304
self._set_msg_status(_msgid, enable, scope, line)
301305
return
302306

303-
# msgid is report id?
304-
if msgid.lower().startswith('rp'):
305-
if enable:
306-
self.enable_report(msgid)
307-
else:
308-
self.disable_report(msgid)
309-
return
307+
# TODO: Need to add enable/disable report back?
310308

311309
try:
312310
# msgid is a symbolic or numeric msgid.
@@ -555,6 +553,24 @@ def _print_checker_doc(checker_name, info, stream=None):
555553
print("", file=stream)
556554
print("", file=stream)
557555

556+
def add_stats(self, **kwargs):
557+
"""Add some stats entries to the statistic dictionary.
558+
559+
:param kwargs: The stats to add to the statistic dictionary.
560+
561+
:returns: The new statistic dictionary.
562+
:rtype: dict
563+
564+
:raises AssertionError: If there is a key conflict.
565+
"""
566+
for key, value in six.iteritems(kwargs):
567+
if key[-1] == '_':
568+
key = key[:-1]
569+
assert key not in self.stats
570+
self.stats[key] = value
571+
return self.stats
572+
573+
558574
class FileState(object):
559575
"""Hold internal state specific to the currently analyzed file"""
560576

@@ -784,9 +800,7 @@ def list_messages(self):
784800

785801

786802
class ReportsHandlerMixIn(object):
787-
"""a mix-in class containing all the reports and stats manipulation
788-
related methods for the main lint class
789-
"""
803+
"""A report handlers organises and calls report methods."""
790804

791805
_POST_CHECKER = object()
792806

@@ -847,6 +861,12 @@ def disable_report(self, reportid):
847861
reportid = reportid.upper()
848862
self._reports_state[reportid] = False
849863

864+
def disable_reporters(self):
865+
"""Disable all reporters."""
866+
for _reporters in self._reports.values():
867+
for report_id, _, _ in _reporters:
868+
self.disable_report(report_id)
869+
850870
def report_is_enabled(self, reportid):
851871
"""return true if the report associated to the given identifier is
852872
enabled
@@ -856,7 +876,7 @@ def report_is_enabled(self, reportid):
856876
def make_reports(self, stats, old_stats):
857877
"""render registered reports"""
858878
sect = Section('Report',
859-
'%s statements analysed.'% (self.stats['statement']))
879+
'%s statements analysed.'% (stats['statement']))
860880
for checker in self.report_order():
861881
for reportid, r_title, r_cb in self._reports[checker]:
862882
if not self.report_is_enabled(reportid):
@@ -870,16 +890,6 @@ def make_reports(self, stats, old_stats):
870890
sect.append(report_sect)
871891
return sect
872892

873-
def add_stats(self, **kwargs):
874-
"""add some stats entries to the statistic dictionary
875-
raise an AssertionError if there is a key conflict
876-
"""
877-
for key, value in six.iteritems(kwargs):
878-
if key[-1] == '_':
879-
key = key[:-1]
880-
assert key not in self.stats
881-
self.stats[key] = value
882-
return self.stats
883893

884894
def _basename_in_blacklist_re(base_name, black_list_re):
885895
"""Determines if the basename is matched in a regex blacklist

0 commit comments

Comments
 (0)