summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2022-05-27 12:16:58 -0400
committerGitHub <noreply@github.com>2022-05-27 12:16:58 -0400
commita7ff1fd597f32686403b9f3a160b03dd55617d00 (patch)
tree0c7d66c3c473943d89e2032601edb812b6bb5c7b /pylint
parenta6a23ecabfd5cc7d43642013255b828ac85352d6 (diff)
downloadpylint-git-a7ff1fd597f32686403b9f3a160b03dd55617d00.tar.gz
Allow disabling `bad-option-value` and `unrecognized-option` with `--disable=all` (#6691)
Previously, due to the order in which options are parsed (config file, then command line), any unrecognized or bad options in the config file would emit messages unconditionally, even if suppressed on the CLI.
Diffstat (limited to 'pylint')
-rw-r--r--pylint/config/callback_actions.py10
-rw-r--r--pylint/config/config_initialization.py16
-rw-r--r--pylint/lint/message_state_handler.py12
-rw-r--r--pylint/lint/pylinter.py9
4 files changed, 40 insertions, 7 deletions
diff --git a/pylint/config/callback_actions.py b/pylint/config/callback_actions.py
index 8ca2a2d6c..15a42daea 100644
--- a/pylint/config/callback_actions.py
+++ b/pylint/config/callback_actions.py
@@ -381,8 +381,9 @@ class _DisableAction(_AccessLinterObjectAction):
try:
self.linter.disable(msgid)
except exceptions.UnknownMessageError:
- msg = f"{option_string}. Don't recognize message {msgid}."
- self.linter.add_message("bad-option-value", args=msg, line=0)
+ self.linter._stashed_bad_option_value_messages[
+ self.linter.current_name
+ ].append((option_string, msgid))
class _EnableAction(_AccessLinterObjectAction):
@@ -401,8 +402,9 @@ class _EnableAction(_AccessLinterObjectAction):
try:
self.linter.enable(msgid)
except exceptions.UnknownMessageError:
- msg = f"{option_string}. Don't recognize message {msgid}."
- self.linter.add_message("bad-option-value", args=msg, line=0)
+ self.linter._stashed_bad_option_value_messages[
+ self.linter.current_name
+ ].append((option_string, msgid))
class _OutputFormatAction(_AccessLinterObjectAction):
diff --git a/pylint/config/config_initialization.py b/pylint/config/config_initialization.py
index 49dfa24fd..b5bd31234 100644
--- a/pylint/config/config_initialization.py
+++ b/pylint/config/config_initialization.py
@@ -31,7 +31,7 @@ def _config_initialization(
# Set the current module to the configuration file
# to allow raising messages on the configuration file.
- linter.set_current_module(str(config_file) if config_file else None)
+ linter.set_current_module(str(config_file) if config_file else "")
# Read the configuration file
config_file_parser = _ConfigurationFileParser(verbose_mode, linter)
@@ -51,12 +51,12 @@ def _config_initialization(
if "load-plugins" in config_data:
linter.load_plugin_modules(utils._splitstrip(config_data["load-plugins"]))
+ unrecognized_options_message = None
# First we parse any options from a configuration file
try:
linter._parse_configuration_file(config_args)
except _UnrecognizedOptionError as exc:
- msg = ", ".join(exc.options)
- linter.add_message("unrecognized-option", line=0, args=msg)
+ unrecognized_options_message = ", ".join(exc.options)
# Then, if a custom reporter is provided as argument, it may be overridden
# by file parameters, so we re-set it here. We do this before command line
@@ -83,6 +83,16 @@ def _config_initialization(
msg = ", ".join(unrecognized_options)
linter._arg_parser.error(f"Unrecognized option found: {msg}")
+ # Now that config file and command line options have been loaded
+ # with all disables, it is safe to emit messages
+ if unrecognized_options_message is not None:
+ linter.set_current_module(str(config_file) if config_file else "")
+ linter.add_message(
+ "unrecognized-option", args=unrecognized_options_message, line=0
+ )
+
+ linter._emit_bad_option_value()
+
# Set the current module to configuration as we don't know where
# the --load-plugins key is coming from
linter.set_current_module("Command line or configuration file")
diff --git a/pylint/lint/message_state_handler.py b/pylint/lint/message_state_handler.py
index 2477502bd..31278dc59 100644
--- a/pylint/lint/message_state_handler.py
+++ b/pylint/lint/message_state_handler.py
@@ -6,6 +6,7 @@ from __future__ import annotations
import sys
import tokenize
+from collections import defaultdict
from typing import TYPE_CHECKING
from pylint import exceptions, interfaces
@@ -53,6 +54,17 @@ class _MessageStateHandler:
"enable-msg": self._options_methods["enable"],
}
self._pragma_lineno: dict[str, int] = {}
+ # TODO: 3.0: Update key type to str when current_name is always str
+ self._stashed_bad_option_value_messages: defaultdict[
+ str | None, list[tuple[str | None, str]]
+ ] = defaultdict(list)
+ """Bad option values for --enable and --disable are encountered too early to
+ warn about them, i.e. before all option providers have been fully parsed.
+
+ Thus,
+ this dict stores option_value and msg_id needed to (later) emit the
+ bad-option-value messages keyed on module names.
+ """
def _set_one_msg_status(
self, scope: str, msg: MessageDefinition, line: int | None, enable: bool
diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py
index 7ab822025..0dc9b8c0d 100644
--- a/pylint/lint/pylinter.py
+++ b/pylint/lint/pylinter.py
@@ -1196,3 +1196,12 @@ class PyLinter(
message_definition.msgid,
line,
)
+
+ def _emit_bad_option_value(self) -> None:
+ for modname in self._stashed_bad_option_value_messages:
+ self.linter.set_current_module(modname)
+ values = self._stashed_bad_option_value_messages[modname]
+ for option_string, msg_id in values:
+ msg = f"{option_string}. Don't recognize message {msg_id}."
+ self.add_message("bad-option-value", args=msg, line=0)
+ self._stashed_bad_option_value_messages = collections.defaultdict(list)