summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshley Whetter <ashley@awhetter.co.uk>2018-05-14 09:13:11 -0700
committerAshley Whetter <ashley@awhetter.co.uk>2019-02-09 13:40:29 -0800
commite4e0e0fd4cc95bc181ef30b84d384d2724333687 (patch)
treedc83db99eee18c7cee4e9eed6f1c4518609a104d
parent1ae6c7648ee0d6b3462c70569a772a82154fda69 (diff)
downloadpylint-git-e4e0e0fd4cc95bc181ef30b84d384d2724333687.tar.gz
PluginRegistry can handle messages
-rw-r--r--pylint/lint.py176
-rw-r--r--pylint/utils.py46
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]]