Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark no-self-use as moved to extensions #6932

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pylint/config/callback_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,10 @@ def _call(
for msgid in utils._check_csv(values[0]):
try:
xabling_function(msgid)
except exceptions.DeletedMessageError as e:
except (
exceptions.DeletedMessageError,
exceptions.MessageBecameExtensionError,
) as e:
self.linter._stashed_messages[
(self.linter.current_name, "useless-option-value")
].append((option_string, str(e)))
Expand Down
11 changes: 11 additions & 0 deletions pylint/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ def __init__(self, msgid_or_symbol: str, removal_explanation: str):
)


class MessageBecameExtensionError(UnknownMessageError):
"""Raised when a message id or symbol that was moved to an optional
extension is encountered.
"""

def __init__(self, msgid_or_symbol: str, moved_explanation: str):
super().__init__(
f"'{msgid_or_symbol}' was moved to an optional extension, see {moved_explanation}."
)


class EmptyReportError(Exception):
"""Raised when a report is empty and so should not be displayed."""

Expand Down
5 changes: 4 additions & 1 deletion pylint/lint/message_state_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ def process_tokens(self, tokens: list[tokenize.TokenInfo]) -> None:
l_start -= 1
try:
meth(msgid, "module", l_start)
except exceptions.DeletedMessageError as e:
except (
exceptions.DeletedMessageError,
exceptions.MessageBecameExtensionError,
) as e:
self.linter.add_message(
"useless-option-value",
args=(pragma_repr.action, e),
Expand Down
29 changes: 29 additions & 0 deletions pylint/message/_deleted_message_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ class DeletedMessage(NamedTuple):
DeletedMessage("W0111", "assign-to-new-keyword"),
],
}
MOVED_TO_EXTENSIONS = {
"https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers": [
DeletedMessage("R0201", "no-self-use")
],
}


@lru_cache(maxsize=None)
Expand All @@ -148,3 +153,27 @@ def is_deleted_msgid(msgid: str) -> str | None:
):
return explanation
return None


@lru_cache(maxsize=None)
def is_moved_symbol(symbol: str) -> str | None:
"""Return the explanation for moving if the message was moved to extensions."""
for explanation, moved_messages in MOVED_TO_EXTENSIONS.items():
for moved_message in moved_messages:
if symbol == moved_message.symbol or any(
symbol == m[1] for m in moved_message.old_names
):
return explanation
return None


@lru_cache(maxsize=None)
def is_moved_msgid(msgid: str) -> str | None:
"""Return the explanation for moving if the message was moved to extensions."""
for explanation, moved_messages in MOVED_TO_EXTENSIONS.items():
for moved_message in moved_messages:
if msgid == moved_message.msgid or any(
msgid == m[0] for m in moved_message.old_names
):
return explanation
return None
15 changes: 14 additions & 1 deletion pylint/message/message_id_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
from pylint.exceptions import (
DeletedMessageError,
InvalidMessageError,
MessageBecameExtensionError,
UnknownMessageError,
)
from pylint.message._deleted_message_ids import is_deleted_msgid, is_deleted_symbol
from pylint.message._deleted_message_ids import (
is_deleted_msgid,
is_deleted_symbol,
is_moved_msgid,
is_moved_symbol,
)


class MessageIdStore:
Expand Down Expand Up @@ -128,20 +134,27 @@ 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
moved_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)
if deletion_reason is None:
moved_reason = is_moved_msgid(msgid)
else:
symbol = msgid_or_symbol
msgid = self.__symbol_to_msgid.get(msgid_or_symbol)
if not msgid:
deletion_reason = is_deleted_symbol(symbol)
if deletion_reason is None:
moved_reason = is_moved_symbol(symbol)
if not msgid or not symbol:
if deletion_reason is not None:
raise DeletedMessageError(msgid_or_symbol, deletion_reason)
if moved_reason is not None:
raise MessageBecameExtensionError(msgid_or_symbol, moved_reason)
error_msg = f"No such message id or symbol '{msgid_or_symbol}'."
raise UnknownMessageError(error_msg)
ids = self.__old_names.get(msgid, [msgid])
Expand Down
12 changes: 12 additions & 0 deletions tests/functional/b/bad_option_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,33 @@
# pylint: disable=C05048 # [unknown-option-value]
# Standard disable with deleted symbol
# pylint: disable=execfile-builtin # [useless-option-value]
# Standard disable with symbol moved to extension
# pylint: disable=no-self-use # [useless-option-value]
# Standard disable with deleted msgid
# pylint: disable=W1656 # [useless-option-value]
# Standard disable with msgid moved to extension
# pylint: disable=R0201 # [useless-option-value]
# disable-next with unknown value
# pylint: disable-next=R78948 # [unknown-option-value]
# disable-next with deleted symbol
# pylint: disable-next=deprecated-types-field # [useless-option-value]
# disable-next with deleted msgid
# pylint: disable-next=W1634 # [useless-option-value]
# disable-next with symbol moved to extension
# pylint: disable-next=no-self-use # [useless-option-value]
# disable-next with msgid moved to extension
# pylint: disable-next=R0201 # [useless-option-value]

# enable with unknown value
# pylint:enable=W04044 # [unknown-option-value]
# enable with deleted symbol
# pylint:enable=dict-values-not-iterating # [useless-option-value]
# enable with symbol moved to extension
# pylint: enable=no-self-use # [useless-option-value]
# enable with deleted msgid
# pylint:enable=W1622 # [useless-option-value]
# enable with msgid moved to extension
# pylint: enable=R0201 # [useless-option-value]

# Standard disable with deleted old name symbol of deleted message
# pylint: disable=no-space-after-operator # [useless-option-value]
Expand Down
24 changes: 15 additions & 9 deletions tests/functional/b/bad_option_value.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
unknown-option-value:4:0:None:None::Unknown option value for 'disable', expected a valid pylint message and got 'C05048':HIGH
useless-option-value:6:0:None:None::"Useless option value for 'disable', 'execfile-builtin' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:8:0:None:None::"Useless option value for 'disable', 'W1656' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
unknown-option-value:10:0:None:None::Unknown option value for 'disable-next', expected a valid pylint message and got 'R78948':HIGH
useless-option-value:12:0:None:None::"Useless option value for 'disable-next', 'deprecated-types-field' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:14:0:None:None::"Useless option value for 'disable-next', 'W1634' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
unknown-option-value:17:0:None:None::Unknown option value for 'enable', expected a valid pylint message and got 'W04044':HIGH
useless-option-value:19:0:None:None::"Useless option value for 'enable', 'dict-values-not-iterating' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:21:0:None:None::"Useless option value for 'enable', 'W1622' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:24:0:None:None::"Useless option value for 'disable', 'no-space-after-operator' was removed from pylint, see https://github.com/PyCQA/pylint/pull/3577.":HIGH
useless-option-value:26:0:None:None::"Useless option value for 'disable', 'C0323' was removed from pylint, see https://github.com/PyCQA/pylint/pull/3577.":HIGH
useless-option-value:8:0:None:None::"Useless option value for 'disable', 'no-self-use' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
useless-option-value:10:0:None:None::"Useless option value for 'disable', 'W1656' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:12:0:None:None::"Useless option value for 'disable', 'R0201' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
unknown-option-value:14:0:None:None::Unknown option value for 'disable-next', expected a valid pylint message and got 'R78948':HIGH
useless-option-value:16:0:None:None::"Useless option value for 'disable-next', 'deprecated-types-field' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:18:0:None:None::"Useless option value for 'disable-next', 'W1634' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:20:0:None:None::"Useless option value for 'disable-next', 'no-self-use' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
useless-option-value:22:0:None:None::"Useless option value for 'disable-next', 'R0201' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
unknown-option-value:25:0:None:None::Unknown option value for 'enable', expected a valid pylint message and got 'W04044':HIGH
useless-option-value:27:0:None:None::"Useless option value for 'enable', 'dict-values-not-iterating' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:29:0:None:None::"Useless option value for 'enable', 'no-self-use' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
useless-option-value:31:0:None:None::"Useless option value for 'enable', 'W1622' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942.":HIGH
useless-option-value:33:0:None:None::"Useless option value for 'enable', 'R0201' was moved to an optional extension, see https://pylint.pycqa.org/en/latest/whatsnew/2/2.14/summary.html#removed-checkers.":HIGH
useless-option-value:36:0:None:None::"Useless option value for 'disable', 'no-space-after-operator' was removed from pylint, see https://github.com/PyCQA/pylint/pull/3577.":HIGH
useless-option-value:38:0:None:None::"Useless option value for 'disable', 'C0323' was removed from pylint, see https://github.com/PyCQA/pylint/pull/3577.":HIGH