diff options
author | Ashley Whetter <ashley@awhetter.co.uk> | 2018-05-14 09:13:11 -0700 |
---|---|---|
committer | Ashley Whetter <ashley@awhetter.co.uk> | 2019-02-09 13:40:29 -0800 |
commit | e4e0e0fd4cc95bc181ef30b84d384d2724333687 (patch) | |
tree | dc83db99eee18c7cee4e9eed6f1c4518609a104d | |
parent | 1ae6c7648ee0d6b3462c70569a772a82154fda69 (diff) | |
download | pylint-git-e4e0e0fd4cc95bc181ef30b84d384d2724333687.tar.gz |
PluginRegistry can handle messages
-rw-r--r-- | pylint/lint.py | 176 | ||||
-rw-r--r-- | pylint/utils.py | 46 |
2 files changed, 178 insertions, 44 deletions
diff --git a/pylint/lint.py b/pylint/lint.py index f1a6cccab..caddd2ee1 100644 --- a/pylint/lint.py +++ b/pylint/lint.py @@ -549,7 +549,7 @@ class PyLinter(utils.MessagesHandlerMixIn, checkers.BaseTokenChecker): self.current_name = None self.current_file = None - super().__init__() + super().__init__(config) # provided reports self._dynamic_plugins = set() self._python3_porting_mode = False @@ -568,17 +568,71 @@ class PyLinter(utils.MessagesHandlerMixIn, checkers.BaseTokenChecker): module.load_configuration(self) # checkers manipulation methods ############################################ + def disable(self, msgid, scope="module", line=None, ignore_unknown=False): + """Do not output messages that have the given ID. - def disable_noerror_messages(self): - for msgcat, msgids in self.msgs_store._msgs_by_category.items(): - # enable only messages with 'error' severity and above ('fatal') - if msgcat in ["E", "F"]: - for msgid in msgids: - self.enable(msgid) - else: - for msgid in msgids: - self.disable(msgid) + :param msgid: The ID of the message to disable. + This can also be "all" to disable all messages, + the ID of a category to disable all messages of that category, + or the name of a checker to disable all messages from the checker. + :type msgid: str + + :param scope: Must be "module". Provided for backwards compatibility. + :type scope: str. + + :param line: The line number that the message is disabled on. + :type line: int + + :param ignore_unknown: If this is False, + an :exc:`UnknownMessageError` is raised when a message with the + given ID cannot be found. + If this is True, the exception is not raised. + :param ignore_unknown: bool + + :raises ValueError: If `scope` is anything other than "module". + """ + if scope != "module": + msg = "Messages can be configured on only a module level" + raise ValueError(msg) + + self._set_msg_status( + msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + + def enable(self, msgid, scope="module", line=None, ignore_unknown=False): + """Enable outputting messages that have the given ID. + + :param msgid: The ID of the message to enable. + This can also be "all" to enable all messages, + the ID of a category to enable all messages of that category, + or the name of a checker to enable all messages from the checker. + :type msgid: str + :param scope: Must be "module". Provided for backwards compatibility. + :type scope: str. + + :param line: The line number that the message is enabled on. + :type line: int + + :param ignore_unknown: If this is False, + an :exc:`UnknownMessageError` is raised when a message with the + given ID cannot be found. + If this is True, the exception is not raised. + :param ignore_unknown: bool + + :raises ValueError: If `scope` is anything other than "module". + """ + if scope != "module": + msg = "Messages can be configured on only a module level" + raise ValueError(msg) + + self._set_msg_status( + msgid, enable=True, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + + # checkers manipulation methods ############################################ + + # TODO: Move to plugin registry def error_mode(self): """error mode: enable only errors; no reports, no persistent""" self._error_mode = True @@ -704,11 +758,6 @@ class PyLinter(utils.MessagesHandlerMixIn, checkers.BaseTokenChecker): # pylint: enable=unused-argument - def _init_msg_states(self): - for msg in self.msgs_store.messages: - if not msg.may_be_emitted(): - self._msgs_state[msg.msgid] = False - def check(self, files_or_modules, checkers_): """main checking entry: check a list of files or modules from their name. @@ -837,7 +886,9 @@ class PyLinter(utils.MessagesHandlerMixIn, checkers.BaseTokenChecker): def open(self): """initialize counters""" - self.stats = {"by_module": {}, "by_msg": {}} + self.stats.clear() + self.stats["by_module"] = {} + self.stats["by_msg"] = {} MANAGER.always_load_extensions = self.config.unsafe_load_any_extension MANAGER.max_inferable_values = self.config.limit_inference_results MANAGER.extension_package_whitelist.update(self.config.extension_pkg_whitelist) @@ -948,11 +999,11 @@ class ReportRegistry: return self._reports_state.get(reportid, True) -class PluginRegistry(ReportRegistry): +class PluginRegistry(utils.MessagesHandlerMixIn, ReportRegistry): """A class to register checkers to.""" def __init__(self, linter, register_options=(lambda options: None)): - super(PluginRegistry, self).__init__() + super().__init__(linter.config, linter.msgs_store, linter.stats) self.register_options = register_options self._checkers = collections.defaultdict(list) # TODO: Remove. This is needed for the MessagesHandlerMixIn for now. @@ -965,8 +1016,7 @@ class PluginRegistry(ReportRegistry): self.register_options(linter.options) - # TODO: Move elsewhere - linter.msgs_store.register_messages_from_checker(linter) + self.msgs_store.register_messages_from_checker(linter) def for_all_checkers(self): """Loop through all registered checkers. @@ -1012,14 +1062,13 @@ class PluginRegistry(ReportRegistry): self.register_options(checker.options) - # TODO: Move elsewhere if hasattr(checker, "msgs"): - self._linter.msgs_store.register_messages_from_checker(checker) + self.msgs_store.register_messages_from_checker(checker) # Register the checker, but disable all of its messages. # TODO(cpopa): we should have a better API for this. if not getattr(checker, "enabled", True): - self._linter.disable(checker.name) + self.disable(checker.name) def register_reporter(self, reporter_class): if reporter_class.name in self._reporters: @@ -1036,6 +1085,70 @@ class PluginRegistry(ReportRegistry): def __getattr__(self, attribute): return getattr(self._linter, attribute) + def disable(self, msgid, scope="package", line=None, ignore_unknown=False): + """Do not output messages that have the given ID. + + :param msgid: The ID of the message to disable. + This can also be "all" to disable all messages, + the ID of a category to disable all messages of that category, + or the name of a checker to disable all messages from the checker. + :type msgid: str + + :param scope: Must be "package". Provided for backwards compatibility. + :type scope: str. + + :param line: The line number that the message is disabled on. + This is not used and is provided for backwards compatibility only. + :type line: int + + :param ignore_unknown: If this is False, + an :exc:`UnknownMessageError` is raised when a message with the + given ID cannot be found. + If this is True, the exception is not raised. + :param ignore_unknown: bool + + :raises ValueError: If `scope` is anything other than "package". + """ + if scope != "package": + msg = "Messages can be configured on only a package level" + raise ValueError(msg) + + self._set_msg_status( + msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + + def enable(self, msgid, scope="package", line=None, ignore_unknown=False): + """Enable outputting messages that have the given ID. + + :param msgid: The ID of the message to enable. + This can also be "all" to enable all messages, + the ID of a category to enable all messages of that category, + or the name of a checker to enable all messages from the checker. + :type msgid: str + + :param scope: Must be "package". Provided for backwards compatibility. + :type scope: str. + + :param line: The line number that the message is enabled on. + This is not used and is provided for backwards compatibility only. + :type line: int + + :param ignore_unknown: If this is False, + an :exc:`UnknownMessageError` is raised when a message with the + given ID cannot be found. + If this is True, the exception is not raised. + :param ignore_unknown: bool + + :raises ValueError: If `scope` is anything other than "package". + """ + if scope != "package": + msg = "Messages can be configured on only a package level" + raise ValueError(msg) + + self._set_msg_status( + msgid, enable=True, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + class Runner(object): """A class to manager how the linter runs.""" @@ -1187,10 +1300,10 @@ group are mutually exclusive.", def __init__(self): super().__init__() - self._linter = PyLinter() + self._global_config = config.Configuration() + self._linter = PyLinter(self._global_config) self._plugin_registry = PluginRegistry(self._linter) self._loaded_plugins = set() - self._global_config = config.Configuration() self._reporter = None def run(self, args): @@ -1307,18 +1420,18 @@ group are mutually exclusive.", sys.exit(0) if self._global_config.list_msgs: - self._linter.msgs_store.list_messages() + self._plugin_registry.msgs_store.list_messages() sys.exit(0) if self._global_config.help_msg: msg = utils._splitstrip(self._global_config.help_msg) - self._linter.msgs_store.help_message(msg) + self._plugin_registry.msgs_store.help_message(msg) sys.exit(0) self.load_default_plugins() - self._linter.disable("I") - self._linter.enable("c-extension-no-member") + self._plugin_registry.disable("I") + self._plugin_registry.enable("c-extension-no-member") for checker in self._plugin_registry.for_all_checkers(): checker.config = self._global_config @@ -1369,6 +1482,7 @@ group are mutually exclusive.", if name in self._plugin_registry._reporters: self._reporter = self._plugin_registry._reporters[name]() self._linter.reporter = self._reporter + self._plugin_registry.reporter = self._reporter # TODO: Remove the need to do this self._reporter.linter = self._linter else: @@ -1500,7 +1614,9 @@ group are mutually exclusive.", neededcheckers = [self._linter] for checker in self.get_checkers()[1:]: messages = set( - msg for msg in checker.msgs if self._linter.is_message_enabled(msg) + msg + for msg in checker.msgs + if self._plugin_registry.is_message_enabled(msg) ) if messages or any( self._plugin_registry.report_is_enabled(r[0]) for r in checker.reports diff --git a/pylint/utils.py b/pylint/utils.py index 9c9db0f0b..c6c78207e 100644 --- a/pylint/utils.py +++ b/pylint/utils.py @@ -280,13 +280,14 @@ class MessagesHandlerMixIn: __by_id_managed_msgs = [] # type: ignore - def __init__(self): - self.file_state = FileState() + def __init__(self, config, msgs_store=None, stats=None): + self.config = config + self.file_state = None self._msgs_state = {} self.msg_status = 0 - self.msgs_store = MessagesStore() + self.msgs_store = msgs_store or MessagesStore() self.reporter = None - self.stats = {"by_module": {}, "by_msg": {}} + self.stats = stats or {"by_module": {}, "by_msg": {}} super().__init__() def _checker_messages(self, checker): @@ -407,12 +408,27 @@ class MessagesHandlerMixIn: except UnknownMessageError: return msgid + def disable_noerror_messages(self): + """Enable only error and fatal level messages, disabling all others.""" + for msgcat, msgids in self.msgs_store._msgs_by_category.items(): + if msgcat in ("E", "F"): + for msgid in msgids: + self.enable(msgid) + else: + for msgid in msgids: + self.disable(msgid) + + def _init_msg_states(self): + for msg in self.msgs_store.messages: + if not msg.may_be_emitted(): + self._msgs_state[msg.msgid] = False + def get_message_state_scope(self, msgid, line=None, confidence=UNDEFINED): """Returns the scope at which a message was enabled/disabled.""" if self.config.confidence and confidence.name not in self.config.confidence: return MSG_STATE_CONFIDENCE try: - if line in self.file_state._module_msgs_state[msgid]: + if self.file_state and line in self.file_state._module_msgs_state[msgid]: return MSG_STATE_SCOPE_MODULE except (KeyError, TypeError): return MSG_STATE_SCOPE_CONFIG @@ -441,8 +457,9 @@ class MessagesHandlerMixIn: return False def is_one_message_enabled(self, msgid, line): - if line is None: + if line is None or not self.file_state: return self._msgs_state.get(msgid, True) + try: return self.file_state._module_msgs_state[msgid][line] except KeyError: @@ -529,14 +546,15 @@ class MessagesHandlerMixIn: # should this message be displayed if not self.is_message_enabled(msgid, line, confidence): - self.file_state.handle_ignored_message( - self.get_message_state_scope(msgid, line, confidence), - msgid, - line, - node, - args, - confidence, - ) + if self.file_state: + self.file_state.handle_ignored_message( + self.get_message_state_scope(msgid, line, confidence), + msgid, + line, + node, + args, + confidence, + ) return # update stats msg_cat = MSG_TYPES[msgid[0]] |