From c1405a9767d981470028d7cfddab6f766cbd67cf Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 4 Jun 2022 10:41:54 +0200 Subject: [PATCH] [deleted messages] Add an exception for deleted messages in MessageIdStore --- pylint/exceptions.py | 11 +++++++++ pylint/message/deleted_message_ids.py | 21 +++++++++++++++++ pylint/message/message_id_store.py | 17 +++++++++++--- .../ini/pylintrc_with_deleted_message.2.out | 4 ++++ .../ini/pylintrc_with_deleted_message.ini | 7 ++++++ .../pylintrc_with_deleted_message.result.json | 12 ++++++++++ tests/functional/b/bad_option_value.py | 23 ++++++++++++++++--- tests/functional/b/bad_option_value.txt | 10 +++++++- 8 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 tests/config/functional/ini/pylintrc_with_deleted_message.2.out create mode 100644 tests/config/functional/ini/pylintrc_with_deleted_message.ini create mode 100644 tests/config/functional/ini/pylintrc_with_deleted_message.result.json diff --git a/pylint/exceptions.py b/pylint/exceptions.py index 27fcfe293c8..c99a72fd546 100644 --- a/pylint/exceptions.py +++ b/pylint/exceptions.py @@ -13,6 +13,17 @@ class UnknownMessageError(Exception): """Raised when an unregistered message id is encountered.""" +class DeletedMessageError(UnknownMessageError): + """Raised when a message id or symbol that was deleted from pylint is + encountered. + """ + + def __init__(self, msgid_or_symbol: str, removal_explanation: str): + super().__init__( + f"'{msgid_or_symbol}' was removed from pylint, see {removal_explanation}." + ) + + class EmptyReportError(Exception): """Raised when a report is empty and so should not be displayed.""" diff --git a/pylint/message/deleted_message_ids.py b/pylint/message/deleted_message_ids.py index aa5ba951a4e..c09d8f1bd03 100644 --- a/pylint/message/deleted_message_ids.py +++ b/pylint/message/deleted_message_ids.py @@ -4,6 +4,7 @@ from __future__ import annotations +from functools import lru_cache from typing import NamedTuple @@ -123,3 +124,23 @@ class DeletedMessage(NamedTuple): DeletedMessage("W0111", "assign-to-new-keyword"), ], } + + +@lru_cache(maxsize=None) +def _is_deleted_symbol(symbol: str) -> str | None: + """Return the explanation for removal if the message was removed.""" + for explanation, deleted_messages in _DELETED_MESSAGES_IDS.items(): + for deleted_message in deleted_messages: + if symbol == deleted_message.symbol: + return explanation + return None + + +@lru_cache(maxsize=None) +def _is_deleted_msgid(msgid: str) -> str | None: + """Return the explanation for removal if the message was removed.""" + for explanation, deleted_messages in _DELETED_MESSAGES_IDS.items(): + for deleted_message in deleted_messages: + if msgid == deleted_message.msgid: + return explanation + return None diff --git a/pylint/message/message_id_store.py b/pylint/message/message_id_store.py index bb807dcf6a7..49aebd186eb 100644 --- a/pylint/message/message_id_store.py +++ b/pylint/message/message_id_store.py @@ -6,7 +6,12 @@ from typing import NoReturn -from pylint.exceptions import InvalidMessageError, UnknownMessageError +from pylint.exceptions import ( + DeletedMessageError, + InvalidMessageError, + UnknownMessageError, +) +from pylint.message.deleted_message_ids import _is_deleted_msgid, _is_deleted_symbol class MessageIdStore: @@ -122,18 +127,24 @@ def get_active_msgids(self, msgid_or_symbol: str) -> list[str]: # If we don't have a cached value yet we compute it msgid: str | None + deletion_reason = None if msgid_or_symbol[1:].isdigit(): # Only msgid can have a digit as second letter msgid = msgid_or_symbol.upper() symbol = self.__msgid_to_symbol.get(msgid) + if not symbol: + deletion_reason = _is_deleted_msgid(msgid) else: - msgid = self.__symbol_to_msgid.get(msgid_or_symbol) symbol = msgid_or_symbol + msgid = self.__symbol_to_msgid.get(msgid_or_symbol) + if not msgid: + deletion_reason = _is_deleted_symbol(symbol) if not msgid or not symbol: + if deletion_reason is not None: + raise DeletedMessageError(msgid_or_symbol, deletion_reason) error_msg = f"No such message id or symbol '{msgid_or_symbol}'." raise UnknownMessageError(error_msg) ids = self.__old_names.get(msgid, [msgid]) - # Add to cache self.__active_msgids[msgid_or_symbol] = ids return ids diff --git a/tests/config/functional/ini/pylintrc_with_deleted_message.2.out b/tests/config/functional/ini/pylintrc_with_deleted_message.2.out new file mode 100644 index 00000000000..27b7d35befc --- /dev/null +++ b/tests/config/functional/ini/pylintrc_with_deleted_message.2.out @@ -0,0 +1,4 @@ +************* Module {abspath} +{relpath}:1:0: E0012: Bad option value for --disable. Don't recognize message buffer-builtin. (bad-option-value) +{relpath}:1:0: E0012: Bad option value for --enable. Don't recognize message useless-option-value. (bad-option-value) +{relpath}:1:0: E0012: Bad option value for --enable. Don't recognize message cmp-builtin. (bad-option-value) diff --git a/tests/config/functional/ini/pylintrc_with_deleted_message.ini b/tests/config/functional/ini/pylintrc_with_deleted_message.ini new file mode 100644 index 00000000000..51b82175081 --- /dev/null +++ b/tests/config/functional/ini/pylintrc_with_deleted_message.ini @@ -0,0 +1,7 @@ +# Check that we raise an informational when a deleted messages exists in a .pylintrc file +# See https://github.com/PyCQA/pylint/issues/6794 +[messages control] +disable = logging-not-lazy, buffer-builtin +enable = useless-option-value, locally-disabled, cmp-builtin +jobs = 10 +reports = yes diff --git a/tests/config/functional/ini/pylintrc_with_deleted_message.result.json b/tests/config/functional/ini/pylintrc_with_deleted_message.result.json new file mode 100644 index 00000000000..b41e716032b --- /dev/null +++ b/tests/config/functional/ini/pylintrc_with_deleted_message.result.json @@ -0,0 +1,12 @@ +{ + "functional_append": { + "disable": ["logging-not-lazy"], + "enable": ["locally-disabled"] + }, + "functional_remove": { + "disable": ["locally-disabled"], + "enable": ["logging-not-lazy"] + }, + "jobs": 10, + "reports": true +} diff --git a/tests/functional/b/bad_option_value.py b/tests/functional/b/bad_option_value.py index 073e828da5f..d4a25a616f4 100644 --- a/tests/functional/b/bad_option_value.py +++ b/tests/functional/b/bad_option_value.py @@ -1,4 +1,21 @@ +"""Check unknown or deleted option. """ + +# Standard disable with unknown value +# pylint: disable=C05048 # [bad-option-value] +# Standard disable with deleted symbol +# pylint: disable=execfile-builtin # [bad-option-value] +# Standard disable with deleted msgid +# pylint: disable=W1656 # [bad-option-value] +# disable-next with unknown value +# pylint: disable-next=R78948 # [bad-option-value] +# disable-next with deleted symbol +# pylint: disable-next=deprecated-types-field # [bad-option-value] +# disable-next with deleted msgid +# pylint: disable-next=W1634 # [bad-option-value] + +# enable with unknown value # pylint:enable=W04044 # [bad-option-value] -"""check unknown option -""" -__revision__ = 1 +# enable with deleted symbol +# pylint:enable=no-space-after-comma # [bad-option-value] +# enable with deleted msgid +# pylint:enable=W1622 # [bad-option-value] diff --git a/tests/functional/b/bad_option_value.txt b/tests/functional/b/bad_option_value.txt index cf9e9b0302a..283cc468b7b 100644 --- a/tests/functional/b/bad_option_value.txt +++ b/tests/functional/b/bad_option_value.txt @@ -1 +1,9 @@ -bad-option-value:1:0:None:None::Bad option value for enable. Don't recognize message W04044.:UNDEFINED +bad-option-value:4:0:None:None::Bad option value for disable. Don't recognize message C05048.:UNDEFINED +bad-option-value:6:0:None:None::Bad option value for disable. Don't recognize message execfile-builtin.:UNDEFINED +bad-option-value:8:0:None:None::Bad option value for disable. Don't recognize message W1656.:UNDEFINED +bad-option-value:10:0:None:None::Bad option value for disable-next. Don't recognize message R78948.:UNDEFINED +bad-option-value:12:0:None:None::Bad option value for disable-next. Don't recognize message deprecated-types-field.:UNDEFINED +bad-option-value:14:0:None:None::Bad option value for disable-next. Don't recognize message W1634.:UNDEFINED +bad-option-value:17:0:None:None::Bad option value for enable. Don't recognize message W04044.:UNDEFINED +bad-option-value:19:0:None:None::Bad option value for enable. Don't recognize message no-space-after-comma.:UNDEFINED +bad-option-value:21:0:None:None::Bad option value for enable. Don't recognize message W1622.:UNDEFINED