Skip to content

Commit 19b4fda

Browse files
[literal-comparison] Make the message explicit with the solution
Also update the confidence Closes #5237
1 parent d200f81 commit 19b4fda

File tree

7 files changed

+43
-26
lines changed

7 files changed

+43
-26
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
def is_an_orange(fruit):
2-
return fruit is "orange" # [literal-comparison]
2+
return fruit is "orange" # [literal-comparison]

doc/user_guide/checkers/features.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ Basic checker Messages
168168
When two literals are compared with each other the result is a constant.
169169
Using the constant directly is both easier to read and more performant.
170170
Initializing 'True' and 'False' this way is not required since Python 2.3.
171-
:literal-comparison (R0123): *Comparison to literal*
171+
:literal-comparison (R0123): *In '%s', use '%s' when comparing constant literals not '%s' ('%s')*
172172
Used when comparing an object to a literal, which is usually what you do not
173173
want to do, since you can compare to a different literal than what was
174174
expected altogether.

doc/whatsnew/fragments/5237.other

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The message for ``literal-comparison`` is now more explicit about the problem and the
2+
solution.
3+
4+
Closes #5237

pylint/checkers/base/comparison_checker.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class ComparisonChecker(_BasicChecker):
4848
{"old_names": [("W0154", "old-unidiomatic-typecheck")]},
4949
),
5050
"R0123": (
51-
"Comparison to literal",
51+
"In '%s', use '%s' when comparing constant literals not '%s' ('%s')",
5252
"literal-comparison",
5353
"Used when comparing an object to a literal, which is usually "
5454
"what you do not want to do, since you can compare to a different "
@@ -201,7 +201,20 @@ def _check_literal_comparison(
201201
is_const = isinstance(literal.value, (bytes, str, int, float))
202202

203203
if is_const or is_other_literal:
204-
self.add_message("literal-comparison", node=node)
204+
bad = node.as_string()
205+
if "is not" in bad:
206+
equal_or_not_equal = "!="
207+
is_or_is_not = "is not"
208+
else:
209+
equal_or_not_equal = "=="
210+
is_or_is_not = "is"
211+
good = bad.replace(is_or_is_not, equal_or_not_equal)
212+
self.add_message(
213+
"literal-comparison",
214+
args=(bad, equal_or_not_equal, is_or_is_not, good),
215+
node=node,
216+
confidence=HIGH,
217+
)
205218

206219
def _check_logical_tautology(self, node: nodes.Compare) -> None:
207220
"""Check if identifier is compared against itself.
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
comparison-of-constants:4:3:4:9::"Comparison between constants: '2 is 2' has a constant value":HIGH
2-
literal-comparison:4:3:4:9::Comparison to literal:UNDEFINED
2+
literal-comparison:4:3:4:9::In '2 is 2', use '==' when comparing constant literals not 'is' ('2 == 2'):HIGH
33
comparison-of-constants:7:6:7:12::"Comparison between constants: '2 == 2' has a constant value":HIGH
44
comparison-of-constants:10:6:10:11::"Comparison between constants: '2 > 2' has a constant value":HIGH
55
comparison-of-constants:20:3:20:15::"Comparison between constants: 'True == True' has a constant value":HIGH
66
singleton-comparison:20:3:20:15::Comparison 'True == True' should be 'True is True' if checking for the singleton value True, or 'True' if testing for truthiness:UNDEFINED
7-
literal-comparison:25:3:25:13::Comparison to literal:UNDEFINED
8-
literal-comparison:28:3:28:13::Comparison to literal:UNDEFINED
9-
literal-comparison:31:3:31:14::Comparison to literal:UNDEFINED
7+
literal-comparison:25:3:25:13::In 'CONST is 0', use '==' when comparing constant literals not 'is' ('CONST == 0'):HIGH
8+
literal-comparison:28:3:28:13::In 'CONST is 1', use '==' when comparing constant literals not 'is' ('CONST == 1'):HIGH
9+
literal-comparison:31:3:31:14::In 'CONST is 42', use '==' when comparing constant literals not 'is' ('CONST == 42'):HIGH

tests/functional/l/literal_comparison.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
# pylint: disable=missing-docstring, comparison-with-itself
22

33

4-
if 2 is 2: # [literal-comparison, comparison-of-constants]
4+
if 2 is 2: # [literal-comparison, comparison-of-constants]
55
pass
66

7-
if "a" is b"a": # [literal-comparison, comparison-of-constants]
7+
if "a" is b"a": # [literal-comparison, comparison-of-constants]
88
pass
99

10-
if 2.0 is 3.0: # [literal-comparison, comparison-of-constants]
10+
if 2.0 is 3.0: # [literal-comparison, comparison-of-constants]
1111
pass
1212

1313
if () is (1, 2, 3):
1414
pass
1515

16-
if () is {1:2, 2:3}: # [literal-comparison]
16+
if () is {1:2, 2:3}: # [literal-comparison]
1717
pass
1818

19-
if [] is [4, 5, 6]: # [literal-comparison]
19+
if [] is [4, 5, 6]: # [literal-comparison]
2020
pass
2121

22-
if () is {1, 2, 3}: # [literal-comparison]
22+
if () is {1, 2, 3}: # [literal-comparison]
2323
pass
2424

2525
if () is not {1:2, 2:3}: # [literal-comparison]
+12-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
comparison-of-constants:4:3:4:9::"Comparison between constants: '2 is 2' has a constant value":HIGH
2-
literal-comparison:4:3:4:9::Comparison to literal:UNDEFINED
2+
literal-comparison:4:3:4:9::In '2 is 2', use '==' when comparing constant literals not 'is' ('2 == 2'):HIGH
33
comparison-of-constants:7:3:7:14::"Comparison between constants: 'a is b'a'' has a constant value":HIGH
4-
literal-comparison:7:3:7:14::Comparison to literal:UNDEFINED
4+
literal-comparison:7:3:7:14::In ''a' is b'a'', use '==' when comparing constant literals not 'is' (''a' == b'a''):HIGH
55
comparison-of-constants:10:3:10:13::"Comparison between constants: '2.0 is 3.0' has a constant value":HIGH
6-
literal-comparison:10:3:10:13::Comparison to literal:UNDEFINED
7-
literal-comparison:16:3:16:19::Comparison to literal:UNDEFINED
8-
literal-comparison:19:3:19:18::Comparison to literal:UNDEFINED
9-
literal-comparison:22:3:22:18::Comparison to literal:UNDEFINED
10-
literal-comparison:25:3:25:23::Comparison to literal:UNDEFINED
11-
literal-comparison:28:3:28:22::Comparison to literal:UNDEFINED
12-
literal-comparison:31:3:31:22::Comparison to literal:UNDEFINED
13-
literal-comparison:38:3:38:13::Comparison to literal:UNDEFINED
14-
literal-comparison:41:3:41:13::Comparison to literal:UNDEFINED
15-
literal-comparison:44:3:44:14::Comparison to literal:UNDEFINED
6+
literal-comparison:10:3:10:13::In '2.0 is 3.0', use '==' when comparing constant literals not 'is' ('2.0 == 3.0'):HIGH
7+
literal-comparison:16:3:16:19::"In '() is {1: 2, 2: 3}', use '==' when comparing constant literals not 'is' ('() == {1: 2, 2: 3}')":HIGH
8+
literal-comparison:19:3:19:18::In '[] is [4, 5, 6]', use '==' when comparing constant literals not 'is' ('[] == [4, 5, 6]'):HIGH
9+
literal-comparison:22:3:22:18::In '() is {1, 2, 3}', use '==' when comparing constant literals not 'is' ('() == {1, 2, 3}'):HIGH
10+
literal-comparison:25:3:25:23::"In '() is not {1: 2, 2: 3}', use '!=' when comparing constant literals not 'is not' ('() != {1: 2, 2: 3}')":HIGH
11+
literal-comparison:28:3:28:22::In '[] is not [4, 5, 6]', use '!=' when comparing constant literals not 'is not' ('[] != [4, 5, 6]'):HIGH
12+
literal-comparison:31:3:31:22::In '() is not {1, 2, 3}', use '!=' when comparing constant literals not 'is not' ('() != {1, 2, 3}'):HIGH
13+
literal-comparison:38:3:38:13::In 'CONST is 0', use '==' when comparing constant literals not 'is' ('CONST == 0'):HIGH
14+
literal-comparison:41:3:41:13::In 'CONST is 1', use '==' when comparing constant literals not 'is' ('CONST == 1'):HIGH
15+
literal-comparison:44:3:44:14::In 'CONST is 42', use '==' when comparing constant literals not 'is' ('CONST == 42'):HIGH

0 commit comments

Comments
 (0)