diff options
author | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2021-10-17 10:37:02 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-17 10:37:02 +0200 |
commit | 97048ded8e7528e927f7f7818beb3d5d79662b03 (patch) | |
tree | 03e9ec6e2c314e31b6ed5fd35ea13ecb4d421147 /pylint | |
parent | c332fda9c5e8a2f2bf6588eeb90b3cf5541dc63d (diff) | |
download | pylint-git-97048ded8e7528e927f7f7818beb3d5d79662b03.tar.gz |
Merge ``MessagesHandlerMixIn`` into ``PyLinter`` (#5136)
* Merge ``MessagesHandlerMixIn`` into ``PyLinter``
Diffstat (limited to 'pylint')
-rw-r--r-- | pylint/checkers/misc.py | 14 | ||||
-rw-r--r-- | pylint/lint/pylinter.py | 166 | ||||
-rw-r--r-- | pylint/message/__init__.py | 2 | ||||
-rw-r--r-- | pylint/message/message_handler_mix_in.py | 140 | ||||
-rw-r--r-- | pylint/typing.py | 12 |
5 files changed, 179 insertions, 155 deletions
diff --git a/pylint/checkers/misc.py b/pylint/checkers/misc.py index 9a29cb1fb..8090679e8 100644 --- a/pylint/checkers/misc.py +++ b/pylint/checkers/misc.py @@ -29,13 +29,13 @@ import re import tokenize -from typing import Optional +from typing import List, Optional from astroid import nodes from pylint.checkers import BaseChecker from pylint.interfaces import IRawChecker, ITokenChecker -from pylint.message import MessagesHandlerMixIn +from pylint.typing import ManagedMessage from pylint.utils.pragma_parser import OPTION_PO, PragmaParserError, parse_pragma @@ -54,15 +54,21 @@ class ByIdManagedMessagesChecker(BaseChecker): } options = () + def _clear_by_id_managed_msgs(self) -> None: + self.linter._by_id_managed_msgs.clear() + + def _get_by_id_managed_msgs(self) -> List[ManagedMessage]: + return self.linter._by_id_managed_msgs + def process_module(self, node: nodes.Module) -> None: """Inspect the source file to find messages activated or deactivated by id.""" - managed_msgs = MessagesHandlerMixIn.get_by_id_managed_msgs() + managed_msgs = self._get_by_id_managed_msgs() for (mod_name, msgid, symbol, lineno, is_disabled) in managed_msgs: if mod_name == node.name: verb = "disable" if is_disabled else "enable" txt = f"'{msgid}' is cryptic: use '# pylint: {verb}={symbol}' instead" self.add_message("use-symbolic-message-instead", line=lineno, args=txt) - MessagesHandlerMixIn.clear_by_id_managed_msgs() + self._clear_by_id_managed_msgs() class EncodingChecker(BaseChecker): diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py index 3dce4627c..6e6ccd59b 100644 --- a/pylint/lint/pylinter.py +++ b/pylint/lint/pylinter.py @@ -23,6 +23,7 @@ from pylint.constants import ( MSG_STATE_SCOPE_CONFIG, MSG_STATE_SCOPE_MODULE, MSG_TYPES, + MSG_TYPES_LONG, MSG_TYPES_STATUS, ) from pylint.lint.expand_modules import expand_modules @@ -37,14 +38,14 @@ from pylint.lint.utils import ( get_fatal_error_message, prepare_crash_report, ) -from pylint.message import ( - Message, - MessageDefinition, - MessageDefinitionStore, - MessagesHandlerMixIn, -) +from pylint.message import Message, MessageDefinition, MessageDefinitionStore from pylint.reporters.ureports import nodes as report_nodes -from pylint.typing import FileItem, MessageLocationTuple, ModuleDescriptionDict +from pylint.typing import ( + FileItem, + ManagedMessage, + MessageLocationTuple, + ModuleDescriptionDict, +) from pylint.utils import ASTWalker, FileState, LinterStats, ModuleStats, utils from pylint.utils.pragma_parser import ( OPTION_PO, @@ -163,7 +164,6 @@ MSGS = { # pylint: disable=too-many-instance-attributes,too-many-public-methods class PyLinter( config.OptionsManagerMixIn, - MessagesHandlerMixIn, reporters.ReportsHandlerMixIn, checkers.BaseTokenChecker, ): @@ -540,6 +540,7 @@ class PyLinter( # Attributes related to message (state) handling self.msg_status = 0 self._msgs_state: Dict[str, bool] = {} + self._by_id_managed_msgs: List[ManagedMessage] = [] reporters.ReportsHandlerMixIn.__init__(self) super().__init__( @@ -1516,3 +1517,152 @@ class PyLinter( message_definition.msgid, line, ) + + # Setting the state (disabled/enabled) of messages and registering them + + def _message_symbol(self, msgid: str) -> List[str]: + """Get the message symbol of the given message id + + Return the original message id if the message does not + exist. + """ + try: + return [md.symbol for md in self.msgs_store.get_message_definitions(msgid)] + except exceptions.UnknownMessageError: + return [msgid] + + def _set_one_msg_status( + self, scope: str, msg: MessageDefinition, line: Optional[int], enable: bool + ) -> None: + """Set the status of an individual message""" + if scope == "module": + self.file_state.set_msg_status(msg, line, enable) + if not enable and msg.symbol != "locally-disabled": + self.add_message( + "locally-disabled", line=line, args=(msg.symbol, msg.msgid) + ) + else: + msgs = self._msgs_state + msgs[msg.msgid] = enable + # sync configuration object + self.config.enable = [ + self._message_symbol(mid) for mid, val in sorted(msgs.items()) if val + ] + self.config.disable = [ + self._message_symbol(mid) + for mid, val in sorted(msgs.items()) + if not val + ] + + def _set_msg_status( + self, + msgid: str, + enable: bool, + scope: str = "package", + line: Optional[int] = None, + ignore_unknown: bool = False, + ) -> None: + """Do some tests and then iterate over message defintions to set state""" + assert scope in ("package", "module") + if msgid == "all": + for _msgid in MSG_TYPES: + self._set_msg_status(_msgid, enable, scope, line, ignore_unknown) + return + + # msgid is a category? + category_id = msgid.upper() + if category_id not in MSG_TYPES: + category_id_formatted = MSG_TYPES_LONG.get(category_id) + else: + category_id_formatted = category_id + if category_id_formatted is not None: + for _msgid in self.msgs_store._msgs_by_category.get(category_id_formatted): + self._set_msg_status(_msgid, enable, scope, line) + return + + # msgid is a checker name? + if msgid.lower() in self._checkers: + for checker in self._checkers[msgid.lower()]: + for _msgid in checker.msgs: + self._set_msg_status(_msgid, enable, scope, line) + return + + # msgid is report id? + if msgid.lower().startswith("rp"): + if enable: + self.enable_report(msgid) + else: + self.disable_report(msgid) + return + + try: + # msgid is a symbolic or numeric msgid. + message_definitions = self.msgs_store.get_message_definitions(msgid) + except exceptions.UnknownMessageError: + if ignore_unknown: + return + raise + for message_definition in message_definitions: + self._set_one_msg_status(scope, message_definition, line, enable) + + def _register_by_id_managed_msg( + self, msgid_or_symbol: str, line: Optional[int], is_disabled: bool = True + ) -> None: + """If the msgid is a numeric one, then register it to inform the user + it could furnish instead a symbolic msgid.""" + if msgid_or_symbol[1:].isdigit(): + try: + symbol = self.msgs_store.message_id_store.get_symbol( + msgid=msgid_or_symbol + ) + except exceptions.UnknownMessageError: + return + managed = ManagedMessage( + self.current_name, msgid_or_symbol, symbol, line, is_disabled + ) + self._by_id_managed_msgs.append(managed) + + def disable( + self, + msgid: str, + scope: str = "package", + line: Optional[int] = None, + ignore_unknown: bool = False, + ) -> None: + """Disable a message for a scope""" + self._set_msg_status( + msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + self._register_by_id_managed_msg(msgid, line) + + def disable_next( + self, + msgid: str, + scope: str = "package", + line: Optional[int] = None, + ignore_unknown: bool = False, + ) -> None: + """Disable a message for the next line""" + if not line: + raise exceptions.NoLineSuppliedError + self._set_msg_status( + msgid, + enable=False, + scope=scope, + line=line + 1, + ignore_unknown=ignore_unknown, + ) + self._register_by_id_managed_msg(msgid, line + 1) + + def enable( + self, + msgid: str, + scope: str = "package", + line: Optional[int] = None, + ignore_unknown: bool = False, + ) -> None: + """Enable a message for a scope""" + self._set_msg_status( + msgid, enable=True, scope=scope, line=line, ignore_unknown=ignore_unknown + ) + self._register_by_id_managed_msg(msgid, line, is_disabled=False) diff --git a/pylint/message/__init__.py b/pylint/message/__init__.py index 346e964f1..f3741030a 100644 --- a/pylint/message/__init__.py +++ b/pylint/message/__init__.py @@ -42,13 +42,11 @@ from pylint.message.message import Message from pylint.message.message_definition import MessageDefinition from pylint.message.message_definition_store import MessageDefinitionStore -from pylint.message.message_handler_mix_in import MessagesHandlerMixIn from pylint.message.message_id_store import MessageIdStore __all__ = [ "Message", "MessageDefinition", "MessageDefinitionStore", - "MessagesHandlerMixIn", "MessageIdStore", ] diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py deleted file mode 100644 index 5e2ba9641..000000000 --- a/pylint/message/message_handler_mix_in.py +++ /dev/null @@ -1,140 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE - -from typing import List, Tuple, Union - -from pylint import exceptions -from pylint.constants import MSG_TYPES, MSG_TYPES_LONG - - -class MessagesHandlerMixIn: - """A mix-in class containing all the messages related methods for the main lint class.""" - - __by_id_managed_msgs: List[Tuple[str, str, str, int, bool]] = [] - - def _checker_messages(self, checker): - for known_checker in self._checkers[checker.lower()]: - yield from known_checker.msgs - - @classmethod - def clear_by_id_managed_msgs(cls): - cls.__by_id_managed_msgs.clear() - - @classmethod - def get_by_id_managed_msgs(cls): - return cls.__by_id_managed_msgs - - def _register_by_id_managed_msg(self, msgid_or_symbol: str, line, is_disabled=True): - """If the msgid is a numeric one, then register it to inform the user - it could furnish instead a symbolic msgid.""" - if msgid_or_symbol[1:].isdigit(): - try: - symbol = self.msgs_store.message_id_store.get_symbol(msgid=msgid_or_symbol) # type: ignore - except exceptions.UnknownMessageError: - return - managed = (self.current_name, msgid_or_symbol, symbol, line, is_disabled) # type: ignore - MessagesHandlerMixIn.__by_id_managed_msgs.append(managed) - - def disable(self, msgid, scope="package", line=None, ignore_unknown=False): - self._set_msg_status( - msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown - ) - self._register_by_id_managed_msg(msgid, line) - - def disable_next( - self, - msgid: str, - scope: str = "package", - line: Union[bool, int, None] = None, - ignore_unknown: bool = False, - ): - if not line: - raise exceptions.NoLineSuppliedError - self._set_msg_status( - msgid, - enable=False, - scope=scope, - line=line + 1, - ignore_unknown=ignore_unknown, - ) - self._register_by_id_managed_msg(msgid, line + 1) - - def enable(self, msgid, scope="package", line=None, ignore_unknown=False): - self._set_msg_status( - msgid, enable=True, scope=scope, line=line, ignore_unknown=ignore_unknown - ) - self._register_by_id_managed_msg(msgid, line, is_disabled=False) - - def _set_msg_status( - self, msgid, enable, scope="package", line=None, ignore_unknown=False - ): - assert scope in ("package", "module") - if msgid == "all": - for _msgid in MSG_TYPES: - self._set_msg_status(_msgid, enable, scope, line, ignore_unknown) - return - - # msgid is a category? - category_id = msgid.upper() - if category_id not in MSG_TYPES: - category_id = MSG_TYPES_LONG.get(category_id) - if category_id is not None: - for _msgid in self.msgs_store._msgs_by_category.get(category_id): - self._set_msg_status(_msgid, enable, scope, line) - return - - # msgid is a checker name? - if msgid.lower() in self._checkers: - for checker in self._checkers[msgid.lower()]: - for _msgid in checker.msgs: - self._set_msg_status(_msgid, enable, scope, line) - return - - # msgid is report id? - if msgid.lower().startswith("rp"): - if enable: - self.enable_report(msgid) - else: - self.disable_report(msgid) - return - - try: - # msgid is a symbolic or numeric msgid. - message_definitions = self.msgs_store.get_message_definitions(msgid) - except exceptions.UnknownMessageError: - if ignore_unknown: - return - raise - for message_definition in message_definitions: - self._set_one_msg_status(scope, message_definition, line, enable) - - def _set_one_msg_status(self, scope, msg, line, enable): - if scope == "module": - self.file_state.set_msg_status(msg, line, enable) - if not enable and msg.symbol != "locally-disabled": - self.add_message( - "locally-disabled", line=line, args=(msg.symbol, msg.msgid) - ) - else: - msgs = self._msgs_state - msgs[msg.msgid] = enable - # sync configuration object - self.config.enable = [ - self._message_symbol(mid) for mid, val in sorted(msgs.items()) if val - ] - self.config.disable = [ - self._message_symbol(mid) - for mid, val in sorted(msgs.items()) - if not val - ] - - def _message_symbol(self, msgid): - """Get the message symbol of the given message id - - Return the original message id if the message does not - exist. - """ - try: - return [md.symbol for md in self.msgs_store.get_message_definitions(msgid)] - except exceptions.UnknownMessageError: - return msgid diff --git a/pylint/typing.py b/pylint/typing.py index 2d8e74763..7ea72cff3 100644 --- a/pylint/typing.py +++ b/pylint/typing.py @@ -3,7 +3,7 @@ """A collection of typing utilities.""" import sys -from typing import NamedTuple, Union +from typing import NamedTuple, Optional, Union if sys.version_info >= (3, 8): from typing import Literal, TypedDict @@ -52,3 +52,13 @@ class MessageLocationTuple(NamedTuple): obj: str line: int column: int + + +class ManagedMessage(NamedTuple): + """Tuple with information ahout a managed message of the linter""" + + name: Optional[str] + msgid: str + symbol: str + line: Optional[int] + is_disabled: bool |