Skip to content

Commit f501b87

Browse files
Fix false negative 'use-symbolic-message-instead' and optimize it
use-symbolic-message-instead was not working for message with multiple new names and the function to get the symbol was suboptimal. Also made the solution copy pastable.
1 parent a20c4de commit f501b87

22 files changed

+76
-52
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Release date: TBA
2323
..
2424
Put bug fixes that will be cherry-picked to latest major version here
2525

26+
* ``use-symbolic-message-instead`` now also works on legacy messages like ``C0111`` (``missing-docstring``).
27+
2628
* Remove unwanted print to stdout from ``_emit_no_member``
2729

2830
* Introduce a command-line option to specify pyreverse output directory

pylint/checkers/misc.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@
3434

3535
class ByIdManagedMessagesChecker(BaseChecker):
3636

37-
"""checks for messages that are enabled or disabled by id instead of symbol."""
37+
"""Checks for messages that are enabled or disabled by id instead of symbol."""
3838

3939
__implements__ = IRawChecker
4040

41-
# configuration section name
4241
name = "miscellaneous"
4342
msgs = {
4443
"I0023": (
@@ -51,12 +50,12 @@ class ByIdManagedMessagesChecker(BaseChecker):
5150
options = ()
5251

5352
def process_module(self, module):
54-
"""inspect the source file to find messages activated or deactivated by id."""
53+
"""Inspect the source file to find messages activated or deactivated by id."""
5554
managed_msgs = MessagesHandlerMixIn.get_by_id_managed_msgs()
56-
for (mod_name, msg_id, msg_symbol, lineno, is_disabled) in managed_msgs:
55+
for (mod_name, msgid, symbol, lineno, is_disabled) in managed_msgs:
5756
if mod_name == module.name:
5857
verb = "disable" if is_disabled else "enable"
59-
txt = f"Id '{msg_id}' is used to {verb} '{msg_symbol}' message emission"
58+
txt = f"'{msgid}' is cryptic: use '# pylint: {verb}={symbol}' instead"
6059
self.add_message("use-symbolic-message-instead", line=lineno, args=txt)
6160
MessagesHandlerMixIn.clear_by_id_managed_msgs()
6261

pylint/message/message_handler_mix_in.py

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
33

44
import sys
5+
from typing import List, Tuple
56

67
from pylint.constants import (
78
_SCOPE_EXEMPT,
@@ -21,11 +22,9 @@
2122

2223

2324
class MessagesHandlerMixIn:
24-
"""a mix-in class containing all the messages related methods for the main
25-
lint class
26-
"""
25+
"""A mix-in class containing all the messages related methods for the main lint class."""
2726

28-
__by_id_managed_msgs = [] # type: ignore
27+
__by_id_managed_msgs: List[Tuple[str, str, str, int, bool]] = []
2928

3029
def __init__(self):
3130
self._msgs_state = {}
@@ -43,27 +42,16 @@ def clear_by_id_managed_msgs(cls):
4342
def get_by_id_managed_msgs(cls):
4443
return cls.__by_id_managed_msgs
4544

46-
def _register_by_id_managed_msg(self, msgid, line, is_disabled=True):
45+
def _register_by_id_managed_msg(self, msgid_or_symbol: str, line, is_disabled=True):
4746
"""If the msgid is a numeric one, then register it to inform the user
4847
it could furnish instead a symbolic msgid."""
49-
try:
50-
message_definitions = self.msgs_store.get_message_definitions(msgid)
51-
for message_definition in message_definitions:
52-
if msgid == message_definition.msgid:
53-
MessagesHandlerMixIn.__by_id_managed_msgs.append(
54-
(
55-
self.current_name,
56-
message_definition.msgid,
57-
message_definition.symbol,
58-
line,
59-
is_disabled,
60-
)
61-
)
62-
except UnknownMessageError:
63-
pass
48+
if msgid_or_symbol[1:].isdigit():
49+
symbol = self.msgs_store.message_id_store.get_symbol(msgid=msgid_or_symbol) # type: ignore
50+
managed = (self.current_name, msgid_or_symbol, symbol, line, is_disabled) # type: ignore
51+
MessagesHandlerMixIn.__by_id_managed_msgs.append(managed)
6452

6553
def disable(self, msgid, scope="package", line=None, ignore_unknown=False):
66-
"""don't output message of the given id"""
54+
"""Don't output message of the given id"""
6755
self._set_msg_status(
6856
msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown
6957
)
@@ -195,7 +183,7 @@ def is_one_message_enabled(self, msgid, line):
195183
except KeyError:
196184
# Check if the message's line is after the maximum line existing in ast tree.
197185
# This line won't appear in the ast tree and won't be referred in
198-
#  self.file_state._module_msgs_state
186+
# self.file_state._module_msgs_state
199187
# This happens for example with a commented line at the end of a module.
200188
max_line_number = self.file_state.get_effective_max_line_number()
201189
if max_line_number and line > max_line_number:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
use-symbolic-message-instead:1:0::"'C0103' is cryptic: use '# pylint: disable=invalid-name' instead"
2+
use-symbolic-message-instead:1:0::"'R0904' is cryptic: use '# pylint: disable=too-many-public-methods' instead"
3+
use-symbolic-message-instead:1:0::"'W0201' is cryptic: use '# pylint: disable=attribute-defined-outside-init' instead"

tests/functional/b/base_init_vars.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
use-symbolic-message-instead:1:0::Id 'no-self-use' is used to disable 'no-self-use' message emission
1+
use-symbolic-message-instead:1:0::"'R0201' is cryptic: use '# pylint: disable=no-self-use' instead"

tests/functional/c/classes_meth_could_be_a_function.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pylint: disable=C0111,too-few-public-methods,no-init, useless-object-inheritance
1+
# pylint: disable=C0111,too-few-public-methods,W0232, useless-object-inheritance # [use-symbolic-message-instead,use-symbolic-message-instead]
22
"""
33
#2479
44
@@ -18,7 +18,7 @@ class Aimpl(object):
1818
# disable "method could be a function" on classes which are not overriding
1919
# the factory method because in that case the usage of polymorphism is not
2020
# detected
21-
# pylint: disable=no-self-use
21+
# pylint: disable=R0201 # [use-symbolic-message-instead]
2222
def makex(self):
2323
return XAsub()
2424

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
use-symbolic-message-instead:1:0::Id 'W0232' is used to disable 'no-init' message emission
1+
use-symbolic-message-instead:1:0::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead"
2+
use-symbolic-message-instead:1:0::"'W0232' is cryptic: use '# pylint: disable=no-init' instead"
3+
use-symbolic-message-instead:21:0::"'R0201' is cryptic: use '# pylint: disable=no-self-use' instead"

tests/functional/c/ctor_arguments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Based on tests/functional/a/arguments.py
44
"""
5-
# pylint: disable=C0111,too-few-public-methods,super-init-not-called, useless-object-inheritance
5+
# pylint: disable=C0111,too-few-public-methods,W0231, useless-object-inheritance # [use-symbolic-message-instead,use-symbolic-message-instead]
66

77

88
class Class1Arg(object):

tests/functional/c/ctor_arguments.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use-symbolic-message-instead:5:0::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead"
2+
use-symbolic-message-instead:5:0::"'W0231' is cryptic: use '# pylint: disable=super-init-not-called' instead"
13
no-value-for-parameter:35:0::No value for argument 'first_argument' in constructor call
24
too-many-function-args:36:0::Too many positional arguments for constructor call
35
no-value-for-parameter:38:0::No value for argument 'third_argument' in constructor call
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
use-symbolic-message-instead:1:0::Id 'W0232' is used to disable 'no-init' message emission
1+
use-symbolic-message-instead:1:0::"'W0232' is cryptic: use '# pylint: disable=no-init' instead"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
use-symbolic-message-instead:1:0::Id 'W0232' is used to disable 'no-init' message emission
2-
use-symbolic-message-instead:1:0::Id 'W0613' is used to disable 'unused-argument' message emission
1+
use-symbolic-message-instead:1:0::"'W0232' is cryptic: use '# pylint: disable=no-init' instead"
2+
use-symbolic-message-instead:1:0::"'W0613' is cryptic: use '# pylint: disable=unused-argument' instead"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
use-symbolic-message-instead:1:0::Id 'W0232' is used to disable 'no-init' message emission
1+
use-symbolic-message-instead:1:0::"'W0232' is cryptic: use '# pylint: disable=no-init' instead"
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
# -*- encoding=utf-8 -*-
2-
#pylint: disable=C0111
3-
def foo(): #pylint: disable=C0102
1+
"""Use symbolic message instead are also tested in use_symbolic_message_instead.py"""
2+
# pylint: disable=C0111 # [use-symbolic-message-instead]
3+
4+
5+
def foo(): # pylint: disable=C0102 # [use-symbolic-message-instead]
46
return 1
57

6-
def toto(): #pylint: disable=C0102,R1711 # [use-symbolic-message-instead]
8+
9+
def toto(): # pylint: disable=C0102,R1711 # [use-symbolic-message-instead,use-symbolic-message-instead]
710
return
811

9-
# +1: [missing-function-docstring]
10-
def test_enabled_by_id_msg(): #pylint: enable=C0111
12+
13+
def test_enabled_by_id_msg(): # pylint: enable=C0111 # [use-symbolic-message-instead,missing-function-docstring]
1114
pass
1215

16+
1317
def baz(): #pylint: disable=blacklisted-name
1418
return 1
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
use-symbolic-message-instead:6:0::Id 'R1711' is used to disable 'useless-return' message emission
2-
missing-function-docstring:10:0:test_enabled_by_id_msg:Missing function or method docstring
1+
use-symbolic-message-instead:2:0::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead"
2+
use-symbolic-message-instead:5:0::"'C0102' is cryptic: use '# pylint: disable=blacklisted-name' instead"
3+
use-symbolic-message-instead:9:0::"'C0102' is cryptic: use '# pylint: disable=blacklisted-name' instead"
4+
use-symbolic-message-instead:9:0::"'R1711' is cryptic: use '# pylint: disable=useless-return' instead"
5+
missing-function-docstring:13:0:test_enabled_by_id_msg:Missing function or method docstring
6+
use-symbolic-message-instead:13:0::"'C0111' is cryptic: use '# pylint: enable=missing-docstring' instead"

tests/functional/u/unused/unused_argument.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def using_inner_function(self, etype, size=1):
7676
description=[(etype,)]*size)
7777
def inner(row, col=0, etype=etype, req=self, rset=rset):
7878
"""inner using all its argument"""
79-
# pylint: disable = E1103
79+
# pylint: disable = E1103 # [use-symbolic-message-instead]
8080
return req.vreg.etype_class(etype)(req, rset, row, col)
8181
# pylint: disable = attribute-defined-outside-init
8282
rset.get_entity = inner

tests/functional/u/unused/unused_argument.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ unused-argument:54:13:function:Unused argument 'arg'
55
unused-argument:61:21:AAAA.method:Unused argument 'arg':INFERENCE
66
unused-argument:68:0:AAAA.selected:Unused argument 'args':INFERENCE
77
unused-argument:68:0:AAAA.selected:Unused argument 'kwargs':INFERENCE
8+
use-symbolic-message-instead:79:0::"'E1103' is cryptic: use '# pylint: disable=maybe-no-member' instead"
89
unused-argument:87:23:BBBB.__init__:Unused argument 'arg':INFERENCE
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""Use symbolic message instead are also tested in messages_managed_by_id.py"""
2+
3+
# pylint: disable=C0111,R0903,T1234 # [bad-option-value,use-symbolic-message-instead,use-symbolic-message-instead]
4+
# pylint: enable=C0111 # [use-symbolic-message-instead]
5+
6+
def myfunction(arg): # [missing-function-docstring]
7+
return arg or True
8+
9+
# pylint: disable=C0111 # [use-symbolic-message-instead]
10+
# pylint: enable=R0903 # [use-symbolic-message-instead]
11+
# pylint: disable=R0903 # [use-symbolic-message-instead]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
bad-option-value:3:0::Bad option value 'T1234'
2+
use-symbolic-message-instead:3:0::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead"
3+
use-symbolic-message-instead:3:0::"'R0903' is cryptic: use '# pylint: disable=too-few-public-methods' instead"
4+
use-symbolic-message-instead:4:0::"'C0111' is cryptic: use '# pylint: enable=missing-docstring' instead"
5+
missing-function-docstring:6:0:myfunction:Missing function or method docstring
6+
use-symbolic-message-instead:9:0::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead"
7+
use-symbolic-message-instead:10:0::"'R0903' is cryptic: use '# pylint: enable=too-few-public-methods' instead"
8+
use-symbolic-message-instead:11:0::"'R0903' is cryptic: use '# pylint: disable=too-few-public-methods' instead"

tests/messages/func_i0011.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
I: 1: Id 'W0404' is used to disable 'reimported' message emission
1+
I: 1: 'W0404' is cryptic: use '# pylint: disable=reimported' instead
22
I: 1: Locally disabling reimported (W0404)
33
I: 1: Useless suppression of 'reimported'

tests/messages/func_i0012.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
I: 1: Id 'W0404' is used to enable 'reimported' message emission
1+
I: 1: 'W0404' is cryptic: use '# pylint: enable=reimported' instead

tests/messages/func_i0020.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
I: 7: Id 'W0612' is used to disable 'unused-variable' message emission
1+
I: 7: 'W0612' is cryptic: use '# pylint: disable=unused-variable' instead
22
I: 7: Locally disabling unused-variable (W0612)
33
I: 8: Suppressed 'unused-variable' (from line 7)

tests/messages/func_i0022.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ I: 12: Locally disabling invalid-name (C0103)
99
I: 12: Pragma "disable-msg" is deprecated, use "disable" instead
1010
I: 13: Suppressed 'invalid-name' (from line 12)
1111
I: 14: Pragma "enable-msg" is deprecated, use "enable" instead
12-
I: 16: Id 'C0103' is used to disable 'invalid-name' message emission
12+
I: 16: 'C0103' is cryptic: use '# pylint: disable=invalid-name' instead
1313
I: 16: Locally disabling invalid-name (C0103)
1414
I: 16: Pragma "disable-msg" is deprecated, use "disable" instead
1515
I: 17: Suppressed 'invalid-name' (from line 16)
16-
I: 18: Id 'C0103' is used to enable 'invalid-name' message emission
16+
I: 18: 'C0103' is cryptic: use '# pylint: enable=invalid-name' instead
1717
I: 18: Pragma "enable-msg" is deprecated, use "enable" instead
18-
I: 20: Id 'C0103' is used to disable 'invalid-name' message emission
18+
I: 20: 'C0103' is cryptic: use '# pylint: disable=invalid-name' instead
1919
I: 20: Locally disabling invalid-name (C0103)
2020
I: 21: Suppressed 'invalid-name' (from line 20)
21-
I: 22: Id 'C0103' is used to enable 'invalid-name' message emission
21+
I: 22: 'C0103' is cryptic: use '# pylint: enable=invalid-name' instead

0 commit comments

Comments
 (0)