diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2022-05-27 12:16:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-27 12:16:58 -0400 |
commit | a7ff1fd597f32686403b9f3a160b03dd55617d00 (patch) | |
tree | 0c7d66c3c473943d89e2032601edb812b6bb5c7b /pylint | |
parent | a6a23ecabfd5cc7d43642013255b828ac85352d6 (diff) | |
download | pylint-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.py | 10 | ||||
-rw-r--r-- | pylint/config/config_initialization.py | 16 | ||||
-rw-r--r-- | pylint/lint/message_state_handler.py | 12 | ||||
-rw-r--r-- | pylint/lint/pylinter.py | 9 |
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) |