summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Sassoulas <pierre.sassoulas@gmail.com>2022-06-04 10:41:54 +0200
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2022-06-06 22:27:46 +0200
commit64ee18d0e269f1b7d97b74b1f1fc773d1487d289 (patch)
treef72e31381c0cd80362d01979310e2eaf51da2200
parent8542af7845e3e87d77ec883ca55c630b9a7f60ea (diff)
downloadpylint-git-64ee18d0e269f1b7d97b74b1f1fc773d1487d289.tar.gz
[deleted messages] Add an exception for deleted messages in MessageIdStore
-rw-r--r--pylint/config/utils.py3
-rw-r--r--pylint/exceptions.py11
-rw-r--r--pylint/message/_deleted_message_ids.py21
-rw-r--r--pylint/message/message_id_store.py17
-rw-r--r--script/get_unused_message_id_category.py4
-rw-r--r--tests/config/functional/ini/pylintrc_with_deleted_message.2.out4
-rw-r--r--tests/config/functional/ini/pylintrc_with_deleted_message.ini7
-rw-r--r--tests/config/functional/ini/pylintrc_with_deleted_message.result.json12
-rw-r--r--tests/functional/b/bad_option_value.py23
-rw-r--r--tests/functional/b/bad_option_value.txt10
-rw-r--r--tests/message/test_no_removed_msgid_or_symbol_used.py4
11 files changed, 103 insertions, 13 deletions
diff --git a/pylint/config/utils.py b/pylint/config/utils.py
index 6ad609789..10bd1a30a 100644
--- a/pylint/config/utils.py
+++ b/pylint/config/utils.py
@@ -203,9 +203,8 @@ def _enable_all_extensions(run: Run, value: str | None) -> None:
PREPROCESSABLE_OPTIONS: dict[
str, tuple[bool, Callable[[Run, str | None], None], int]
] = { # pylint: disable=consider-using-namedtuple-or-dataclass
- # pylint: disable=wrong-spelling-in-comment
# Argparse by default allows abbreviations. It behaves differently
- # if you turn this off, so we also turn it on. We mimick this
+ # if you turn this off, so we also turn it on. We mimic this
# by allowing some abbreviations or incorrect spelling here.
# The integer at the end of the tuple indicates how many letters
# should match, include the '-'. 0 indicates a full match.
diff --git a/pylint/exceptions.py b/pylint/exceptions.py
index 27fcfe293..c99a72fd5 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 349d30f66..7a8872db7 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 @@ DELETED_MESSAGES_IDS = {
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 bb807dcf6..508c67b31 100644
--- a/pylint/message/message_id_store.py
+++ b/pylint/message/message_id_store.py
@@ -6,7 +6,12 @@ from __future__ import annotations
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 @@ class MessageIdStore:
# 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/script/get_unused_message_id_category.py b/script/get_unused_message_id_category.py
index 621487551..4ea8390ee 100644
--- a/script/get_unused_message_id_category.py
+++ b/script/get_unused_message_id_category.py
@@ -8,7 +8,7 @@ from __future__ import annotations
from pylint.checkers import initialize as initialize_checkers
from pylint.extensions import initialize as initialize_extensions
from pylint.lint.pylinter import PyLinter
-from pylint.message.deleted_message_ids import _DELETED_MSGID_PREFIXES
+from pylint.message._deleted_message_ids import DELETED_MSGID_PREFIXES
def register_all_checkers_and_plugins(linter: PyLinter) -> None:
@@ -21,7 +21,7 @@ def register_all_checkers_and_plugins(linter: PyLinter) -> None:
def get_next_code_category(message_ids: list[str]) -> int:
categories = sorted({int(i[:2]) for i in message_ids})
# We add the prefixes for deleted checkers
- categories += _DELETED_MSGID_PREFIXES
+ categories += DELETED_MSGID_PREFIXES
for i in categories:
if i + 1 not in categories:
return i + 1
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 000000000..27b7d35be
--- /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 000000000..51b821750
--- /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 000000000..b41e71603
--- /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 073e828da..d4a25a616 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 cf9e9b030..283cc468b 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
diff --git a/tests/message/test_no_removed_msgid_or_symbol_used.py b/tests/message/test_no_removed_msgid_or_symbol_used.py
index 833ab2fc9..3b0134235 100644
--- a/tests/message/test_no_removed_msgid_or_symbol_used.py
+++ b/tests/message/test_no_removed_msgid_or_symbol_used.py
@@ -3,7 +3,7 @@
# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
from pylint.lint import PyLinter
-from pylint.message.deleted_message_ids import _DELETED_MESSAGES_IDS
+from pylint.message._deleted_message_ids import DELETED_MESSAGES_IDS
def test_no_removed_msgid_or_symbol_used(linter: PyLinter) -> None:
@@ -12,7 +12,7 @@ def test_no_removed_msgid_or_symbol_used(linter: PyLinter) -> None:
This could cause occasional bugs, but more importantly confusion and inconsistencies
when searching for old msgids online. See https://github.com/PyCQA/pylint/issues/5729
"""
- for deleted_messages in _DELETED_MESSAGES_IDS.values():
+ for deleted_messages in DELETED_MESSAGES_IDS.values():
for msgid, symbol, old_names in deleted_messages:
linter.msgs_store.message_id_store.register_message_definition(
msgid, symbol, old_names