Skip to content

Commit 92f28ce

Browse files
[bad-option-value] Add a 'useless-option-value' message
So it's possible to to distinguish between genuine typoes and old configuration that could be cleaned. We use old_names to decrease message type to warning
1 parent f8756ed commit 92f28ce

30 files changed

+100
-63
lines changed

doc/data/messages/b/bad-option-value/bad.py

-2
This file was deleted.

doc/data/messages/b/bad-option-value/good.py

-2
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# pylint: disable=missnig-docstring # [unknown-option-value]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# pylint: disable=missing-docstring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""'bad-continuation' was removed from pylint in https://github.com/PyCQA/pylint/pull/3571"""
2+
3+
# pylint: disable=bad-continuation # [useless-option-value]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
You can disable this check if you don't want to cleanup your configuration of old messages.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""'bad-continuation' was removed from pylint in https://github.com/PyCQA/pylint/pull/3571"""

doc/user_guide/messages/messages_overview.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ All messages in the error category:
5858
error/bad-except-order
5959
error/bad-exception-context
6060
error/bad-format-character
61-
error/bad-option-value
6261
error/bad-plugin-value
6362
error/bad-reversed-sequence
6463
error/bad-str-strip-call
@@ -178,6 +177,7 @@ All renamed messages in the error category:
178177
:titlesonly:
179178

180179
error/bad-context-manager
180+
error/bad-option-value
181181
error/maybe-no-member
182182
error/old-non-iterator-returned-2
183183
error/old-unbalanced-tuple-unpacking
@@ -306,6 +306,7 @@ All messages in the warning category:
306306
warning/try-except-raise
307307
warning/unbalanced-tuple-unpacking
308308
warning/undefined-loop-variable
309+
warning/unknown-option-value
309310
warning/unnecessary-ellipsis
310311
warning/unnecessary-lambda
311312
warning/unnecessary-pass
@@ -507,6 +508,7 @@ All messages in the refactor category:
507508
refactor/use-list-literal
508509
refactor/use-set-for-membership
509510
refactor/useless-object-inheritance
511+
refactor/useless-option-value
510512
refactor/useless-return
511513

512514
All renamed messages in the refactor category:

doc/whatsnew/2/2.14/full.rst

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ Release date: TBA
3535

3636
Closes #6624
3737

38+
* ``bad-option-value`` (E0012) is now a warning ``unknown-option-value`` (W0012). Deleted messages that do not exist
39+
anymore in pylint now raise ``useless-option-value`` (R0022) instead of ``bad-option-value``. This allows to
40+
distinguish between genuine typos and configuration that could be cleaned up. Existing message disables for
41+
``bad-option-value`` will still work on both new messages.
42+
43+
Refs #6794
44+
3845

3946
What's New in Pylint 2.14.0?
4047
----------------------------

pylint/config/callback_actions.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,14 @@ def _call(
378378
for msgid in utils._check_csv(values[0]):
379379
try:
380380
xabling_function(msgid)
381+
except exceptions.DeletedMessageError as e:
382+
self.linter._stashed_messages[
383+
(self.linter.current_name, "useless-option-value")
384+
].append((option_string, str(e)))
381385
except exceptions.UnknownMessageError:
382-
self.linter._stashed_messages[self.linter.current_name].append(
383-
(option_string, msgid)
384-
)
386+
self.linter._stashed_messages[
387+
(self.linter.current_name, "unknown-option-value")
388+
].append((option_string, msgid))
385389

386390
@abc.abstractmethod
387391
def __call__(

pylint/lint/message_state_handler.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __init__(self, linter: PyLinter) -> None:
5757
self._pragma_lineno: dict[str, int] = {}
5858
# TODO: 3.0: Update key type to str when current_name is always str
5959
self._stashed_messages: defaultdict[
60-
str | None, list[tuple[str | None, str]]
60+
tuple[str | None, str], list[tuple[str | None, str]]
6161
] = defaultdict(list)
6262
"""Some messages in the options (for --enable and --disable) are encountered
6363
too early to warn about them.
@@ -410,13 +410,21 @@ def process_tokens(self, tokens: list[tokenize.TokenInfo]) -> None:
410410
l_start -= 1
411411
try:
412412
meth(msgid, "module", l_start)
413+
except exceptions.DeletedMessageError as e:
414+
self.linter.add_message(
415+
"useless-option-value",
416+
args=(pragma_repr.action, e),
417+
line=start[0],
418+
confidence=HIGH,
419+
)
413420
except exceptions.UnknownMessageError:
414421
self.linter.add_message(
415-
"bad-option-value",
422+
"unknown-option-value",
416423
args=(pragma_repr.action, msgid),
417424
line=start[0],
418425
confidence=HIGH,
419426
)
427+
420428
except UnRecognizedOptionError as err:
421429
self.linter.add_message(
422430
"unrecognized-inline-option", args=err.token, line=start[0]

pylint/lint/pylinter.py

+23-9
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,24 @@ def _load_reporter_by_class(reporter_class: str) -> type[BaseReporter]:
193193
"Used when an unknown inline option is encountered.",
194194
{"scope": WarningScope.LINE},
195195
),
196-
"E0012": (
197-
"Bad option value for '%s', expected a valid pylint message and got '%s'",
198-
"bad-option-value",
199-
"Used when a bad value for an option is encountered.",
200-
{"scope": WarningScope.LINE},
196+
"W0012": (
197+
"Unknown option value for '%s', expected a valid pylint message and got '%s'",
198+
"unknown-option-value",
199+
"Used when an unknown value is encountered for an option.",
200+
{
201+
"scope": WarningScope.LINE,
202+
"old_names": [("E0012", "bad-option-value")],
203+
},
204+
),
205+
"R0022": (
206+
"Useless option value for '%s', %s",
207+
"useless-option-value",
208+
"Used when a value for an option that is now deleted from pylint"
209+
" is encountered.",
210+
{
211+
"scope": WarningScope.LINE,
212+
"old_names": [("E0012", "bad-option-value")],
213+
},
201214
),
202215
"E0013": (
203216
"Plugin '%s' is impossible to load, is it installed ? ('%s')",
@@ -1227,12 +1240,13 @@ def add_ignored_message(
12271240
)
12281241

12291242
def _emit_stashed_messages(self) -> None:
1230-
for modname, values in self._stashed_messages.items():
1243+
for keys, values in self._stashed_messages.items():
1244+
modname, symbol = keys
12311245
self.linter.set_current_module(modname)
1232-
for option_string, msgid in values:
1246+
for args in values:
12331247
self.add_message(
1234-
"bad-option-value",
1235-
args=(option_string, msgid),
1248+
symbol,
1249+
args=args,
12361250
line=0,
12371251
confidence=HIGH,
12381252
)

tests/config/functional/ini/pylintrc_with_deleted_message.2.out

-4
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
************* Module {abspath}
2+
{relpath}:1:0: R0022: Useless option value for '--disable', 'buffer-builtin' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942. (useless-option-value)
3+
{relpath}:1:0: R0022: Useless option value for '--enable', 'cmp-builtin' was removed from pylint, see https://github.com/PyCQA/pylint/pull/4942. (useless-option-value)

tests/config/functional/ini/pylintrc_with_deleted_message.result.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"functional_append": {
33
"disable": ["logging-not-lazy"],
4-
"enable": ["locally-disabled"]
4+
"enable": ["locally-disabled", "useless-option-value"]
55
},
66
"functional_remove": {
7-
"disable": ["locally-disabled"],
7+
"disable": ["locally-disabled", "useless-option-value"],
88
"enable": ["logging-not-lazy"]
99
},
1010
"jobs": 10,

tests/config/functional/ini/pylintrc_with_missing_comma.2.out

-3
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
************* Module {abspath}
2+
{relpath}:1:0: W0012: Unknown option value for '--disable', expected a valid pylint message and got 'logging-not-lazylogging-format-interpolation' (unknown-option-value)
3+
{relpath}:1:0: W0012: Unknown option value for '--enable', expected a valid pylint message and got 'locally-disabledsuppressed-message' (unknown-option-value)

tests/config/functional/setup_cfg/do_not_read_other_tools_configuration/setup.2.out

-2
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
************* Module {abspath}
2+
{relpath}:1:0: W0012: Unknown option value for '--enable', expected a valid pylint message and got 'useless-supression' (unknown-option-value)

tests/config/functional/toml/issue_3122/toml_with_missing_comma.2.out

-3
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
************* Module {abspath}
2+
{relpath}:1:0: W0012: Unknown option value for '--disable', expected a valid pylint message and got 'logging-not-lazylogging-format-interpolation' (unknown-option-value)
3+
{relpath}:1:0: W0012: Unknown option value for '--enable', expected a valid pylint message and got 'locally-disabledsuppressed-message' (unknown-option-value)

tests/config/functional/toml/unknown_msgid/enable_unknown_msgid.2.out

-3
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
************* Module {abspath}
2+
{relpath}:1:0: W0012: Unknown option value for '--disable', expected a valid pylint message and got 'logging-not-layzy' (unknown-option-value)
3+
{relpath}:1:0: W0012: Unknown option value for '--enable', expected a valid pylint message and got 'C00000' (unknown-option-value)

tests/config/test_config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_unknown_message_id(capsys: CaptureFixture) -> None:
6060
"""Check that we correctly raise a message on an unknown id."""
6161
Run([str(EMPTY_MODULE), "--disable=12345"], exit=False)
6262
output = capsys.readouterr()
63-
assert "Command line:1:0: E0012: Bad option value for '--disable'" in output.out
63+
assert "Command line:1:0: W0012: Unknown option value for '--disable'" in output.out
6464

6565

6666
def test_unknown_option_name(capsys: CaptureFixture) -> None:
+11-11
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
"""Check unknown or deleted option. """
22

33
# Standard disable with unknown value
4-
# pylint: disable=C05048 # [bad-option-value]
4+
# pylint: disable=C05048 # [unknown-option-value]
55
# Standard disable with deleted symbol
6-
# pylint: disable=execfile-builtin # [bad-option-value]
6+
# pylint: disable=execfile-builtin # [useless-option-value]
77
# Standard disable with deleted msgid
8-
# pylint: disable=W1656 # [bad-option-value]
8+
# pylint: disable=W1656 # [useless-option-value]
99
# disable-next with unknown value
10-
# pylint: disable-next=R78948 # [bad-option-value]
10+
# pylint: disable-next=R78948 # [unknown-option-value]
1111
# disable-next with deleted symbol
12-
# pylint: disable-next=deprecated-types-field # [bad-option-value]
12+
# pylint: disable-next=deprecated-types-field # [useless-option-value]
1313
# disable-next with deleted msgid
14-
# pylint: disable-next=W1634 # [bad-option-value]
14+
# pylint: disable-next=W1634 # [useless-option-value]
1515

1616
# enable with unknown value
17-
# pylint:enable=W04044 # [bad-option-value]
17+
# pylint:enable=W04044 # [unknown-option-value]
1818
# enable with deleted symbol
19-
# pylint:enable=no-space-after-comma # [bad-option-value]
19+
# pylint:enable=dict-values-not-iterating # [useless-option-value]
2020
# enable with deleted msgid
21-
# pylint:enable=W1622 # [bad-option-value]
21+
# pylint:enable=W1622 # [useless-option-value]
2222

2323
# Standard disable with deleted old name symbol of deleted message
24-
# pylint: disable=no-space-after-operator # [bad-option-value]
24+
# pylint: disable=no-space-after-operator # [bad-option-value] <= This is wrong
2525
# Standard disable with deleted old name msgid of deleted message
26-
# pylint: disable=C0323 # [bad-option-value]
26+
# pylint: disable=C0323 # [bad-option-value] <= This is wrong
+9-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
bad-option-value:4:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'C05048':HIGH
2-
bad-option-value:6:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'execfile-builtin':HIGH
3-
bad-option-value:8:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'W1656':HIGH
4-
bad-option-value:10:0:None:None::Bad option value for 'disable-next', expected a valid pylint message and got 'R78948':HIGH
5-
bad-option-value:12:0:None:None::Bad option value for 'disable-next', expected a valid pylint message and got 'deprecated-types-field':HIGH
6-
bad-option-value:14:0:None:None::Bad option value for 'disable-next', expected a valid pylint message and got 'W1634':HIGH
7-
bad-option-value:17:0:None:None::Bad option value for 'enable', expected a valid pylint message and got 'W04044':HIGH
8-
bad-option-value:19:0:None:None::Bad option value for 'enable', expected a valid pylint message and got 'no-space-after-comma':HIGH
9-
bad-option-value:21:0:None:None::Bad option value for 'enable', expected a valid pylint message and got 'W1622':HIGH
1+
unknown-option-value:4:0:None:None::Unknown option value for 'disable', expected a valid pylint message and got 'C05048':HIGH
2+
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
3+
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
4+
unknown-option-value:10:0:None:None::Unknown option value for 'disable-next', expected a valid pylint message and got 'R78948':HIGH
5+
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
6+
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
7+
unknown-option-value:17:0:None:None::Unknown option value for 'enable', expected a valid pylint message and got 'W04044':HIGH
8+
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
9+
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
1010
bad-option-value:24:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'no-space-after-operator':HIGH
1111
bad-option-value:26:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'C0323':HIGH

tests/functional/b/bad_option_value_disable.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
# pylint: enable=bad-option-value
99

10-
var = 1 # pylint: disable=a-removed-option # [bad-option-value]
10+
var = 1 # pylint: disable=a-removed-option # [unknown-option-value]
1111

1212
# bad-option-value needs to be disabled before the bad option
13-
var = 1 # pylint: disable=a-removed-option, bad-option-value # [bad-option-value]
13+
var = 1 # pylint: disable=a-removed-option, bad-option-value # [unknown-option-value]
1414
var = 1 # pylint: disable=bad-option-value, a-removed-option
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
bad-option-value:10:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'a-removed-option':HIGH
2-
bad-option-value:13:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'a-removed-option':HIGH
1+
unknown-option-value:10:0:None:None::Unknown option value for 'disable', expected a valid pylint message and got 'a-removed-option':HIGH
2+
unknown-option-value:13:0:None:None::Unknown option value for 'disable', expected a valid pylint message and got 'a-removed-option':HIGH

tests/functional/u/use/use_symbolic_message_instead.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pylint: disable=C0111,R0903,T1234 # [bad-option-value,use-symbolic-message-instead,use-symbolic-message-instead]
1+
# pylint: disable=C0111,R0903,T1234 # [unknown-option-value,use-symbolic-message-instead,use-symbolic-message-instead]
22
# pylint: enable=c0111,w0223 # [use-symbolic-message-instead,use-symbolic-message-instead]
33

44
def my_function(arg): # [missing-function-docstring]

tests/functional/u/use/use_symbolic_message_instead.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
bad-option-value:1:0:None:None::Bad option value for 'disable', expected a valid pylint message and got 'T1234':HIGH
1+
unknown-option-value:1:0:None:None::Unknown option value for 'disable', expected a valid pylint message and got 'T1234':HIGH
22
use-symbolic-message-instead:1:0:None:None::"'C0111' is cryptic: use '# pylint: disable=missing-docstring' instead":UNDEFINED
33
use-symbolic-message-instead:1:0:None:None::"'R0903' is cryptic: use '# pylint: disable=too-few-public-methods' instead":UNDEFINED
44
use-symbolic-message-instead:2:0:None:None::"'c0111' is cryptic: use '# pylint: enable=missing-docstring' instead":UNDEFINED

0 commit comments

Comments
 (0)