summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromarandlorraine <64254276+omarandlorraine@users.noreply.github.com>2022-05-04 22:54:09 +0100
committerGitHub <noreply@github.com>2022-05-04 23:54:09 +0200
commit6486514dcce0ae8c4b18e1fc26570173ffeef59e (patch)
tree34195bbd5fe6e53469fb9c77eeb0a68fd2566564
parent1c87f3f0781e1eda638432da2fd80d3510e52ffe (diff)
downloadpylint-git-6486514dcce0ae8c4b18e1fc26570173ffeef59e.tar.gz
Add `comparison-of-constants` checker (#6413)
Co-authored-by: Sam M W <smw@alertergroup.co.uk> Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com> Co-authored-by: Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>
-rw-r--r--ChangeLog4
-rw-r--r--doc/data/messages/c/comparison-of-constants/bad.py2
-rw-r--r--doc/data/messages/c/comparison-of-constants/good.py2
-rw-r--r--doc/whatsnew/2.14.rst4
-rw-r--r--pylint/checkers/base/comparison_checker.py28
-rw-r--r--tests/functional/a/access/access_to_protected_members.py4
-rw-r--r--tests/functional/a/assert_on_tuple.py2
-rw-r--r--tests/functional/c/comparison_of_constants.py51
-rw-r--r--tests/functional/c/comparison_of_constants.txt9
-rw-r--r--tests/functional/c/comparison_with_callable.py2
-rw-r--r--tests/functional/c/consider/consider_using_get.py2
-rw-r--r--tests/functional/c/consider/consider_using_in.py2
-rw-r--r--tests/functional/d/deprecated/deprecated_methods_py38.py2
-rw-r--r--tests/functional/e/excess_escapes.py2
-rw-r--r--tests/functional/ext/check_elif/check_elif.py2
-rw-r--r--tests/functional/ext/comparison_placement/misplaced_comparison_constant.py1
-rw-r--r--tests/functional/ext/comparison_placement/misplaced_comparison_constant.txt12
-rw-r--r--tests/functional/i/import_outside_toplevel.py1
-rw-r--r--tests/functional/i/import_outside_toplevel.txt22
-rw-r--r--tests/functional/l/literal_comparison.py6
-rw-r--r--tests/functional/l/literal_comparison.txt3
-rw-r--r--tests/functional/l/logical_tautology.py12
-rw-r--r--tests/functional/l/logical_tautology.txt6
-rw-r--r--tests/functional/m/membership_protocol.py2
-rw-r--r--tests/functional/m/misplaced_bare_raise.py1
-rw-r--r--tests/functional/m/misplaced_bare_raise.txt14
-rw-r--r--tests/functional/n/nan_comparison_check.py2
-rw-r--r--tests/functional/s/singleton_comparison.py2
-rw-r--r--tests/functional/s/superfluous_parens.py8
-rw-r--r--tests/functional/t/too/too_many_boolean_expressions.py2
-rw-r--r--tests/functional/u/unnecessary/unnecessary_ellipsis.py2
-rw-r--r--tests/functional/u/unnecessary/unnecessary_not.py2
-rw-r--r--tests/functional/u/use/use_implicit_booleaness_not_len.py3
-rw-r--r--tests/functional/u/use/use_implicit_booleaness_not_len.txt43
-rw-r--r--tests/functional/u/useless/useless_else_on_loop.py10
-rw-r--r--tests/functional/u/using_constant_test.py2
-rw-r--r--tests/functional/u/using_constant_test.txt1
37 files changed, 195 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 0d8df9e0a..7586f1378 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,10 @@ Release date: TBA
..
Put new features here and also in 'doc/whatsnew/2.14.rst'
+* Added new checker ``comparison-of-constants``.
+
+ Closes #6076
+
* Started ignoring underscore as a local variable for ``too-many-locals``.
Closes #6488
diff --git a/doc/data/messages/c/comparison-of-constants/bad.py b/doc/data/messages/c/comparison-of-constants/bad.py
new file mode 100644
index 000000000..2ea0c4223
--- /dev/null
+++ b/doc/data/messages/c/comparison-of-constants/bad.py
@@ -0,0 +1,2 @@
+def is_the_answer() -> bool:
+ return 42 == 42 # [comparison-of-constants]
diff --git a/doc/data/messages/c/comparison-of-constants/good.py b/doc/data/messages/c/comparison-of-constants/good.py
new file mode 100644
index 000000000..731bb1612
--- /dev/null
+++ b/doc/data/messages/c/comparison-of-constants/good.py
@@ -0,0 +1,2 @@
+def is_the_answer(meaning_of_life: int) -> bool:
+ return meaning_of_life == 42
diff --git a/doc/whatsnew/2.14.rst b/doc/whatsnew/2.14.rst
index cc6193855..2931fae03 100644
--- a/doc/whatsnew/2.14.rst
+++ b/doc/whatsnew/2.14.rst
@@ -12,6 +12,10 @@ Summary -- Release highlights
New checkers
============
+* Added new checker ``comparison-of-constants``.
+
+ Closes #6076
+
* Added new checker ``typevar-name-mismatch``: TypeVar must be assigned to a variable with the same name as its name argument.
Closes #5224
diff --git a/pylint/checkers/base/comparison_checker.py b/pylint/checkers/base/comparison_checker.py
index 7220f0259..97cf08c26 100644
--- a/pylint/checkers/base/comparison_checker.py
+++ b/pylint/checkers/base/comparison_checker.py
@@ -9,6 +9,7 @@ from astroid import nodes
from pylint.checkers import utils
from pylint.checkers.base.basic_checker import _BasicChecker
+from pylint.interfaces import HIGH
LITERAL_NODE_TYPES = (nodes.Const, nodes.Dict, nodes.List, nodes.Set)
COMPARISON_OPERATORS = frozenset(("==", "!=", "<", ">", "<=", ">="))
@@ -58,6 +59,13 @@ class ComparisonChecker(_BasicChecker):
"comparison-with-itself",
"Used when something is compared against itself.",
),
+ "R0133": (
+ "Comparison between constants: '%s %s %s' has a constant value",
+ "comparison-of-constants",
+ "When two literals are compared with each other the result is a constant. "
+ "Using the constant directly is both easier to read and more performant. "
+ "Initializing 'True' and 'False' this way is not required since Python 2.3.",
+ ),
"W0143": (
"Comparing against a callable, did you omit the parenthesis?",
"comparison-with-callable",
@@ -212,6 +220,24 @@ class ComparisonChecker(_BasicChecker):
suggestion = f"{left_operand} {operator} {right_operand}"
self.add_message("comparison-with-itself", node=node, args=(suggestion,))
+ def _check_two_literals_being_compared(self, node: nodes.Compare) -> None:
+ """Check if two literals are being compared; this is always a logical tautology."""
+ left_operand = node.left
+ if not isinstance(left_operand, nodes.Const):
+ return
+
+ right_operand = node.ops[0][1]
+ if not isinstance(right_operand, nodes.Const):
+ return
+
+ operator = node.ops[0][0]
+ self.add_message(
+ "comparison-of-constants",
+ node=node,
+ args=(left_operand.value, operator, right_operand.value),
+ confidence=HIGH,
+ )
+
def _check_callable_comparison(self, node):
operator = node.ops[0][0]
if operator not in COMPARISON_OPERATORS:
@@ -240,6 +266,7 @@ class ComparisonChecker(_BasicChecker):
"unidiomatic-typecheck",
"literal-comparison",
"comparison-with-itself",
+ "comparison-of-constants",
"comparison-with-callable",
"nan-comparison",
)
@@ -247,6 +274,7 @@ class ComparisonChecker(_BasicChecker):
self._check_callable_comparison(node)
self._check_logical_tautology(node)
self._check_unidiomatic_typecheck(node)
+ self._check_two_literals_being_compared(node)
# NOTE: this checker only works with binary comparisons like 'x == 42'
# but not 'x == y == 42'
if len(node.ops) != 1:
diff --git a/tests/functional/a/access/access_to_protected_members.py b/tests/functional/a/access/access_to_protected_members.py
index 7d732dcc5..a521a6467 100644
--- a/tests/functional/a/access/access_to_protected_members.py
+++ b/tests/functional/a/access/access_to_protected_members.py
@@ -85,9 +85,9 @@ class Issue1802(object):
Test a correct access as the access to protected member
is inside a special method even if it is deeply nested
"""
- if 2 > 1:
+ if 2 > 1: # pylint: disable=comparison-of-constants
if isinstance(other, self.__class__):
- if "answer" == "42":
+ if "answer" == "42": # pylint: disable=comparison-of-constants
return self._foo == other._foo
return False
diff --git a/tests/functional/a/assert_on_tuple.py b/tests/functional/a/assert_on_tuple.py
index 57dbd0907..3ceb6e167 100644
--- a/tests/functional/a/assert_on_tuple.py
+++ b/tests/functional/a/assert_on_tuple.py
@@ -1,6 +1,6 @@
'''Assert check example'''
-# pylint: disable=comparison-with-itself
+# pylint: disable=comparison-with-itself, comparison-of-constants
assert (1 == 1, 2 == 2), "no error"
assert (1 == 1, 2 == 2) # [assert-on-tuple]
assert 1 == 1, "no error"
diff --git a/tests/functional/c/comparison_of_constants.py b/tests/functional/c/comparison_of_constants.py
new file mode 100644
index 000000000..bfe4b8cdb
--- /dev/null
+++ b/tests/functional/c/comparison_of_constants.py
@@ -0,0 +1,51 @@
+# pylint: disable=missing-docstring, comparison-with-itself, invalid-name
+
+
+if 2 is 2: # [literal-comparison, comparison-of-constants]
+ pass
+
+while 2 == 2: # [comparison-of-constants]
+ pass
+
+while 2 > 2: # [comparison-of-constants]
+ pass
+
+n = 2
+if 2 != n:
+ pass
+
+if n != 1 + 1:
+ pass
+
+if True == True: # [comparison-of-constants, singleton-comparison]
+ pass
+
+CONST = 24
+
+if CONST is 0: # [literal-comparison]
+ pass
+
+if CONST is 1: # [literal-comparison]
+ pass
+
+if CONST is 42: # [literal-comparison]
+ pass
+
+if 0 < CONST < 42:
+ pass
+
+if 0 < n < 42:
+ pass
+
+if True == n != 42:
+ pass
+
+if 0 == n != 42:
+ pass
+
+
+print(0 < n < 42)
+print(0 <= n < 42 )
+print(n < 1 < n*42 < 42)
+print(42> n <= 0)
+print(0 == n > 42)
diff --git a/tests/functional/c/comparison_of_constants.txt b/tests/functional/c/comparison_of_constants.txt
new file mode 100644
index 000000000..1a0984024
--- /dev/null
+++ b/tests/functional/c/comparison_of_constants.txt
@@ -0,0 +1,9 @@
+comparison-of-constants:4:3:4:9::"Comparison between constants: '2 is 2' has a constant value":HIGH
+literal-comparison:4:3:4:9::Comparison to literal:UNDEFINED
+comparison-of-constants:7:6:7:12::"Comparison between constants: '2 == 2' has a constant value":HIGH
+comparison-of-constants:10:6:10:11::"Comparison between constants: '2 > 2' has a constant value":HIGH
+comparison-of-constants:20:3:20:15::"Comparison between constants: 'True == True' has a constant value":HIGH
+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
+literal-comparison:25:3:25:13::Comparison to literal:UNDEFINED
+literal-comparison:28:3:28:13::Comparison to literal:UNDEFINED
+literal-comparison:31:3:31:14::Comparison to literal:UNDEFINED
diff --git a/tests/functional/c/comparison_with_callable.py b/tests/functional/c/comparison_with_callable.py
index 2afe43035..4b7123099 100644
--- a/tests/functional/c/comparison_with_callable.py
+++ b/tests/functional/c/comparison_with_callable.py
@@ -1,4 +1,4 @@
-# pylint: disable = disallowed-name, missing-docstring, useless-return, invalid-name, no-self-use, line-too-long, useless-object-inheritance
+# pylint: disable = disallowed-name, missing-docstring, useless-return, invalid-name, no-self-use, line-too-long, useless-object-inheritance, comparison-of-constants
def foo():
return None
diff --git a/tests/functional/c/consider/consider_using_get.py b/tests/functional/c/consider/consider_using_get.py
index 0b71431d0..728fccd50 100644
--- a/tests/functional/c/consider/consider_using_get.py
+++ b/tests/functional/c/consider/consider_using_get.py
@@ -1,4 +1,4 @@
-# pylint: disable=missing-docstring,invalid-name,using-constant-test,invalid-sequence-index,undefined-variable
+# pylint: disable=missing-docstring,invalid-name,using-constant-test,invalid-sequence-index,undefined-variable, comparison-of-constants
dictionary = {}
key = 'key'
diff --git a/tests/functional/c/consider/consider_using_in.py b/tests/functional/c/consider/consider_using_in.py
index 5bc06e438..c2b725173 100644
--- a/tests/functional/c/consider/consider_using_in.py
+++ b/tests/functional/c/consider/consider_using_in.py
@@ -1,4 +1,4 @@
-# pylint: disable=missing-docstring, invalid-name, pointless-statement, undefined-variable, literal-comparison, line-too-long, unneeded-not, too-few-public-methods, use-implicit-booleaness-not-comparison
+# pylint: disable=missing-docstring, invalid-name, pointless-statement, undefined-variable, literal-comparison, line-too-long, unneeded-not, too-few-public-methods, use-implicit-booleaness-not-comparison, comparison-of-constants
value = value1 = 1
value2 = 2
diff --git a/tests/functional/d/deprecated/deprecated_methods_py38.py b/tests/functional/d/deprecated/deprecated_methods_py38.py
index 35ec88f5a..34f08a8be 100644
--- a/tests/functional/d/deprecated/deprecated_methods_py38.py
+++ b/tests/functional/d/deprecated/deprecated_methods_py38.py
@@ -1,5 +1,5 @@
""" Functional tests for method deprecation. """
-# pylint: disable=missing-docstring, super-init-not-called, not-callable
+# pylint: disable=missing-docstring, super-init-not-called, not-callable, comparison-of-constants
import base64
import inspect
import logging
diff --git a/tests/functional/e/excess_escapes.py b/tests/functional/e/excess_escapes.py
index a81dc7b9a..d680c2b5e 100644
--- a/tests/functional/e/excess_escapes.py
+++ b/tests/functional/e/excess_escapes.py
@@ -1,4 +1,4 @@
-# pylint:disable=pointless-string-statement, fixme, comparison-with-itself
+# pylint:disable=pointless-string-statement, fixme, comparison-with-itself, comparison-of-constants
"""Stray backslash escapes may be missing a raw-string prefix."""
# pylint: disable=redundant-u-string-prefix
diff --git a/tests/functional/ext/check_elif/check_elif.py b/tests/functional/ext/check_elif/check_elif.py
index f03c76839..f10e78511 100644
--- a/tests/functional/ext/check_elif/check_elif.py
+++ b/tests/functional/ext/check_elif/check_elif.py
@@ -1,4 +1,4 @@
-# pylint: disable=no-else-raise,unsupported-membership-test,using-constant-test
+# pylint: disable=no-else-raise,unsupported-membership-test,using-constant-test, comparison-of-constants
"""Checks use of "else if" triggers a refactor message"""
from typing import Union, Sequence, Any, Mapping
diff --git a/tests/functional/ext/comparison_placement/misplaced_comparison_constant.py b/tests/functional/ext/comparison_placement/misplaced_comparison_constant.py
index 0162187bf..0d0296742 100644
--- a/tests/functional/ext/comparison_placement/misplaced_comparison_constant.py
+++ b/tests/functional/ext/comparison_placement/misplaced_comparison_constant.py
@@ -1,6 +1,7 @@
"""Check that the constants are on the right side of the comparisons"""
# pylint: disable=singleton-comparison, missing-docstring, too-few-public-methods, useless-object-inheritance
+# pylint: disable=comparison-of-constants
class MyClass(object):
def __init__(self):
diff --git a/tests/functional/ext/comparison_placement/misplaced_comparison_constant.txt b/tests/functional/ext/comparison_placement/misplaced_comparison_constant.txt
index 22df53950..bc18506c7 100644
--- a/tests/functional/ext/comparison_placement/misplaced_comparison_constant.txt
+++ b/tests/functional/ext/comparison_placement/misplaced_comparison_constant.txt
@@ -1,6 +1,6 @@
-misplaced-comparison-constant:19:11:19:17:bad_comparisons:Comparison should be i >= 5:UNDEFINED
-misplaced-comparison-constant:21:11:21:17:bad_comparisons:Comparison should be i == 1:UNDEFINED
-misplaced-comparison-constant:23:11:23:29:bad_comparisons:Comparison should be dummy_return() > 3:UNDEFINED
-misplaced-comparison-constant:25:11:25:39:bad_comparisons:Comparison should be instance.dummy_return() != 4:UNDEFINED
-misplaced-comparison-constant:27:11:27:29:bad_comparisons:Comparison should be instance.attr == 1:UNDEFINED
-misplaced-comparison-constant:29:11:29:33:bad_comparisons:Comparison should be instance.attr == 'aaa':UNDEFINED
+misplaced-comparison-constant:20:11:20:17:bad_comparisons:Comparison should be i >= 5:UNDEFINED
+misplaced-comparison-constant:22:11:22:17:bad_comparisons:Comparison should be i == 1:UNDEFINED
+misplaced-comparison-constant:24:11:24:29:bad_comparisons:Comparison should be dummy_return() > 3:UNDEFINED
+misplaced-comparison-constant:26:11:26:39:bad_comparisons:Comparison should be instance.dummy_return() != 4:UNDEFINED
+misplaced-comparison-constant:28:11:28:29:bad_comparisons:Comparison should be instance.attr == 1:UNDEFINED
+misplaced-comparison-constant:30:11:30:33:bad_comparisons:Comparison should be instance.attr == 'aaa':UNDEFINED
diff --git a/tests/functional/i/import_outside_toplevel.py b/tests/functional/i/import_outside_toplevel.py
index 3ed7701cc..9796741b0 100644
--- a/tests/functional/i/import_outside_toplevel.py
+++ b/tests/functional/i/import_outside_toplevel.py
@@ -1,4 +1,5 @@
# pylint: disable=unused-import,multiple-imports,no-self-use,missing-docstring,invalid-name,too-few-public-methods
+# pylint: disable=comparison-of-constants
import abc
diff --git a/tests/functional/i/import_outside_toplevel.txt b/tests/functional/i/import_outside_toplevel.txt
index 934112224..66a734925 100644
--- a/tests/functional/i/import_outside_toplevel.txt
+++ b/tests/functional/i/import_outside_toplevel.txt
@@ -1,11 +1,11 @@
-import-outside-toplevel:10:4:10:19:f:Import outside toplevel (symtable):UNDEFINED
-import-outside-toplevel:14:4:14:18:g:Import outside toplevel (os, sys):UNDEFINED
-import-outside-toplevel:18:4:18:24:h:Import outside toplevel (time):UNDEFINED
-import-outside-toplevel:22:4:22:41:i:Import outside toplevel (random, socket):UNDEFINED
-import-outside-toplevel:26:4:26:19:C:Import outside toplevel (tokenize):UNDEFINED
-import-outside-toplevel:29:8:29:21:C.j:Import outside toplevel (turtle):UNDEFINED
-import-outside-toplevel:34:8:34:23:k:Import outside toplevel (tabnanny):UNDEFINED
-import-outside-toplevel:38:4:38:39:j:Import outside toplevel (collections.defaultdict):UNDEFINED
-import-outside-toplevel:42:4:42:48:m:Import outside toplevel (math.sin, math.cos):UNDEFINED
-import-error:50:4:50:21:o:Unable to import 'notastroid':UNDEFINED
-import-outside-toplevel:50:4:50:21:o:Import outside toplevel (notastroid):UNDEFINED
+import-outside-toplevel:11:4:11:19:f:Import outside toplevel (symtable):UNDEFINED
+import-outside-toplevel:15:4:15:18:g:Import outside toplevel (os, sys):UNDEFINED
+import-outside-toplevel:19:4:19:24:h:Import outside toplevel (time):UNDEFINED
+import-outside-toplevel:23:4:23:41:i:Import outside toplevel (random, socket):UNDEFINED
+import-outside-toplevel:27:4:27:19:C:Import outside toplevel (tokenize):UNDEFINED
+import-outside-toplevel:30:8:30:21:C.j:Import outside toplevel (turtle):UNDEFINED
+import-outside-toplevel:35:8:35:23:k:Import outside toplevel (tabnanny):UNDEFINED
+import-outside-toplevel:39:4:39:39:j:Import outside toplevel (collections.defaultdict):UNDEFINED
+import-outside-toplevel:43:4:43:48:m:Import outside toplevel (math.sin, math.cos):UNDEFINED
+import-error:51:4:51:21:o:Unable to import 'notastroid':UNDEFINED
+import-outside-toplevel:51:4:51:21:o:Import outside toplevel (notastroid):UNDEFINED
diff --git a/tests/functional/l/literal_comparison.py b/tests/functional/l/literal_comparison.py
index 4e41caaa4..b5e31a0e7 100644
--- a/tests/functional/l/literal_comparison.py
+++ b/tests/functional/l/literal_comparison.py
@@ -1,13 +1,13 @@
# pylint: disable=missing-docstring, comparison-with-itself
-if 2 is 2: # [literal-comparison]
+if 2 is 2: # [literal-comparison, comparison-of-constants]
pass
-if "a" is b"a": # [literal-comparison]
+if "a" is b"a": # [literal-comparison, comparison-of-constants]
pass
-if 2.0 is 3.0: # [literal-comparison]
+if 2.0 is 3.0: # [literal-comparison, comparison-of-constants]
pass
if () is (1, 2, 3):
diff --git a/tests/functional/l/literal_comparison.txt b/tests/functional/l/literal_comparison.txt
index 38d9b6002..c1a679c76 100644
--- a/tests/functional/l/literal_comparison.txt
+++ b/tests/functional/l/literal_comparison.txt
@@ -1,5 +1,8 @@
+comparison-of-constants:4:3:4:9::"Comparison between constants: '2 is 2' has a constant value":HIGH
literal-comparison:4:3:4:9::Comparison to literal:UNDEFINED
+comparison-of-constants:7:3:7:14::"Comparison between constants: 'a is b'a'' has a constant value":HIGH
literal-comparison:7:3:7:14::Comparison to literal:UNDEFINED
+comparison-of-constants:10:3:10:13::"Comparison between constants: '2.0 is 3.0' has a constant value":HIGH
literal-comparison:10:3:10:13::Comparison to literal:UNDEFINED
literal-comparison:16:3:16:19::Comparison to literal:UNDEFINED
literal-comparison:19:3:19:18::Comparison to literal:UNDEFINED
diff --git a/tests/functional/l/logical_tautology.py b/tests/functional/l/logical_tautology.py
index be133ba87..6c18876f4 100644
--- a/tests/functional/l/logical_tautology.py
+++ b/tests/functional/l/logical_tautology.py
@@ -11,21 +11,21 @@ def foo():
return True
elif arg <= arg: # [comparison-with-itself]
return True
- elif None == None: # [comparison-with-itself]
+ elif None == None: # [comparison-of-constants, comparison-with-itself]
return None
- elif 786 == 786: # [comparison-with-itself]
+ elif 786 == 786: # [comparison-of-constants, comparison-with-itself]
return True
- elif 786 is 786: # [comparison-with-itself]
+ elif 786 is 786: # [comparison-of-constants, comparison-with-itself]
return True
- elif 786 is not 786: # [comparison-with-itself]
+ elif 786 is not 786: # [comparison-of-constants, comparison-with-itself]
return True
elif arg is arg: # [comparison-with-itself]
return True
elif arg is not arg: # [comparison-with-itself]
return True
- elif True is True: # [comparison-with-itself]
+ elif True is True: # [comparison-of-constants, comparison-with-itself]
return True
- elif 666 == 786:
+ elif 666 == 786: # [comparison-of-constants]
return False
else:
return None
diff --git a/tests/functional/l/logical_tautology.txt b/tests/functional/l/logical_tautology.txt
index 775e8a1ac..9397d9862 100644
--- a/tests/functional/l/logical_tautology.txt
+++ b/tests/functional/l/logical_tautology.txt
@@ -2,11 +2,17 @@ comparison-with-itself:6:7:6:17:foo:Redundant comparison - arg == arg:UNDEFINED
comparison-with-itself:8:9:8:19:foo:Redundant comparison - arg != arg:UNDEFINED
comparison-with-itself:10:9:10:18:foo:Redundant comparison - arg > arg:UNDEFINED
comparison-with-itself:12:9:12:19:foo:Redundant comparison - arg <= arg:UNDEFINED
+comparison-of-constants:14:9:14:21:foo:"Comparison between constants: 'None == None' has a constant value":HIGH
comparison-with-itself:14:9:14:21:foo:Redundant comparison - None == None:UNDEFINED
+comparison-of-constants:16:9:16:19:foo:"Comparison between constants: '786 == 786' has a constant value":HIGH
comparison-with-itself:16:9:16:19:foo:Redundant comparison - 786 == 786:UNDEFINED
+comparison-of-constants:18:9:18:19:foo:"Comparison between constants: '786 is 786' has a constant value":HIGH
comparison-with-itself:18:9:18:19:foo:Redundant comparison - 786 is 786:UNDEFINED
+comparison-of-constants:20:9:20:23:foo:"Comparison between constants: '786 is not 786' has a constant value":HIGH
comparison-with-itself:20:9:20:23:foo:Redundant comparison - 786 is not 786:UNDEFINED
comparison-with-itself:22:9:22:19:foo:Redundant comparison - arg is arg:UNDEFINED
comparison-with-itself:24:9:24:23:foo:Redundant comparison - arg is not arg:UNDEFINED
+comparison-of-constants:26:9:26:21:foo:"Comparison between constants: 'True is True' has a constant value":HIGH
comparison-with-itself:26:9:26:21:foo:Redundant comparison - True is True:UNDEFINED
+comparison-of-constants:28:9:28:19:foo:"Comparison between constants: '666 == 786' has a constant value":HIGH
comparison-with-itself:36:18:36:28:bar:Redundant comparison - arg != arg:UNDEFINED
diff --git a/tests/functional/m/membership_protocol.py b/tests/functional/m/membership_protocol.py
index b9a0197ca..152c27704 100644
--- a/tests/functional/m/membership_protocol.py
+++ b/tests/functional/m/membership_protocol.py
@@ -1,4 +1,4 @@
-# pylint: disable=missing-docstring,pointless-statement,expression-not-assigned,too-few-public-methods,import-error,wrong-import-position,no-else-return, comparison-with-itself, useless-object-inheritance, redundant-u-string-prefix
+# pylint: disable=missing-docstring,pointless-statement,expression-not-assigned,too-few-public-methods,import-error,wrong-import-position,no-else-return, comparison-with-itself, useless-object-inheritance, redundant-u-string-prefix comparison-of-constants
# standard types
1 in [1, 2, 3]
diff --git a/tests/functional/m/misplaced_bare_raise.py b/tests/functional/m/misplaced_bare_raise.py
index c704f0122..2170e5f36 100644
--- a/tests/functional/m/misplaced_bare_raise.py
+++ b/tests/functional/m/misplaced_bare_raise.py
@@ -1,5 +1,6 @@
# pylint: disable=missing-docstring, broad-except, unreachable, try-except-raise, raise-missing-from
# pylint: disable=unused-variable, too-few-public-methods, invalid-name, useless-object-inheritance
+# pylint: disable=comparison-of-constants
try:
raise # [misplaced-bare-raise]
diff --git a/tests/functional/m/misplaced_bare_raise.txt b/tests/functional/m/misplaced_bare_raise.txt
index e32bc46f6..d26893e3f 100644
--- a/tests/functional/m/misplaced_bare_raise.txt
+++ b/tests/functional/m/misplaced_bare_raise.txt
@@ -1,7 +1,7 @@
-misplaced-bare-raise:5:4:5:9::The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:35:16:35:21:test1.best:The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:38:4:38:9:test1:The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:39:0:39:5::The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:48:4:48:9::The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:56:4:56:9:A:The raise statement is not inside an except clause:UNDEFINED
-misplaced-bare-raise:67:4:67:9::The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:6:4:6:9::The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:36:16:36:21:test1.best:The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:39:4:39:9:test1:The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:40:0:40:5::The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:49:4:49:9::The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:57:4:57:9:A:The raise statement is not inside an except clause:UNDEFINED
+misplaced-bare-raise:68:4:68:9::The raise statement is not inside an except clause:UNDEFINED
diff --git a/tests/functional/n/nan_comparison_check.py b/tests/functional/n/nan_comparison_check.py
index 99b921cde..dd55e3058 100644
--- a/tests/functional/n/nan_comparison_check.py
+++ b/tests/functional/n/nan_comparison_check.py
@@ -1,5 +1,5 @@
# pylint: disable=missing-docstring, invalid-name
-# pylint: disable=literal-comparison,comparison-with-itself, import-error
+# pylint: disable=literal-comparison,comparison-with-itself, import-error, comparison-of-constants
"""Test detection of NaN value comparison."""
import numpy
diff --git a/tests/functional/s/singleton_comparison.py b/tests/functional/s/singleton_comparison.py
index 8bfd0e887..8eb7c22bd 100644
--- a/tests/functional/s/singleton_comparison.py
+++ b/tests/functional/s/singleton_comparison.py
@@ -1,4 +1,4 @@
-# pylint: disable=missing-docstring, invalid-name, literal-comparison, comparison-with-itself
+# pylint: disable=missing-docstring, invalid-name, literal-comparison, comparison-with-itself, comparison-of-constants
x = 42
a = x is None
b = x == None # [singleton-comparison]
diff --git a/tests/functional/s/superfluous_parens.py b/tests/functional/s/superfluous_parens.py
index 5c91c99ee..db9349cce 100644
--- a/tests/functional/s/superfluous_parens.py
+++ b/tests/functional/s/superfluous_parens.py
@@ -20,9 +20,9 @@ del(DICT['b']) # [superfluous-parens]
del DICT['a']
B = [x for x in ((3, 4))]
-C = [x for x in ((3, 4) if 1 > 0 else (5, 6))]
-D = [x for x in ((3, 4) if 1 > 0 else ((5, 6)))]
-E = [x for x in ((3, 4) if 1 > 0 else ((((5, 6)))))]
+C = [x for x in ((3, 4) if 1 > 0 else (5, 6))] # pylint: disable=comparison-of-constants
+D = [x for x in ((3, 4) if 1 > 0 else ((5, 6)))] # pylint: disable=comparison-of-constants
+E = [x for x in ((3, 4) if 1 > 0 else ((((5, 6)))))] # pylint: disable=comparison-of-constants
# Test assertions
F = "Version 1.0"
@@ -74,4 +74,4 @@ if (A == 2) is not (B == 2):
M = A is not (A <= H)
M = True is not (M == K)
-M = True is not (True is not False)
+M = True is not (True is not False) # pylint: disable=comparison-of-constants
diff --git a/tests/functional/t/too/too_many_boolean_expressions.py b/tests/functional/t/too/too_many_boolean_expressions.py
index e8753859c..07616f1d2 100644
--- a/tests/functional/t/too/too_many_boolean_expressions.py
+++ b/tests/functional/t/too/too_many_boolean_expressions.py
@@ -1,6 +1,6 @@
"""Checks for if statements containing too many boolean expressions"""
-# pylint: disable=invalid-name, comparison-with-itself, chained-comparison, condition-evals-to-constant
+# pylint: disable=invalid-name, comparison-with-itself, chained-comparison, condition-evals-to-constant, comparison-of-constants
x = y = z = 5
if x > -5 and x < 5 and y > -5 and y < 5 and z > -5 and z < 5: # [too-many-boolean-expressions]
diff --git a/tests/functional/u/unnecessary/unnecessary_ellipsis.py b/tests/functional/u/unnecessary/unnecessary_ellipsis.py
index e34de754b..c46fd323a 100644
--- a/tests/functional/u/unnecessary/unnecessary_ellipsis.py
+++ b/tests/functional/u/unnecessary/unnecessary_ellipsis.py
@@ -1,6 +1,6 @@
"""Emit a warning when the ellipsis constant is used and can be avoided"""
-# pylint: disable=missing-docstring, too-few-public-methods, invalid-name, unused-argument
+# pylint: disable=missing-docstring, too-few-public-methods, invalid-name, unused-argument, comparison-of-constants
from typing import List, overload, Union
diff --git a/tests/functional/u/unnecessary/unnecessary_not.py b/tests/functional/u/unnecessary/unnecessary_not.py
index 97acecd73..6b6b51369 100644
--- a/tests/functional/u/unnecessary/unnecessary_not.py
+++ b/tests/functional/u/unnecessary/unnecessary_not.py
@@ -1,7 +1,7 @@
"""Check exceeding negations in boolean expressions trigger warnings"""
# pylint: disable=singleton-comparison,too-many-branches,too-few-public-methods,undefined-variable
-# pylint: disable=literal-comparison, comparison-with-itself, useless-object-inheritance
+# pylint: disable=literal-comparison, comparison-with-itself, useless-object-inheritance, comparison-of-constants
def unneeded_not():
"""This is not ok
"""
diff --git a/tests/functional/u/use/use_implicit_booleaness_not_len.py b/tests/functional/u/use/use_implicit_booleaness_not_len.py
index fa410a81b..4002a6dda 100644
--- a/tests/functional/u/use/use_implicit_booleaness_not_len.py
+++ b/tests/functional/u/use/use_implicit_booleaness_not_len.py
@@ -35,7 +35,8 @@ if z and len('TEST') == 0: # Should be fine
if 0 == len('TEST') < 10: # Should be fine
pass
-if 0 < 1 <= len('TEST') < 10: # Should be fine
+# Should be fine
+if 0 < 1 <= len('TEST') < 10: # [comparison-of-constants]
pass
if 10 > len('TEST') != 0: # Should be fine
diff --git a/tests/functional/u/use/use_implicit_booleaness_not_len.txt b/tests/functional/u/use/use_implicit_booleaness_not_len.txt
index cb77a1f79..11412f5b2 100644
--- a/tests/functional/u/use/use_implicit_booleaness_not_len.txt
+++ b/tests/functional/u/use/use_implicit_booleaness_not_len.txt
@@ -2,24 +2,25 @@ use-implicit-booleaness-not-len:4:3:4:14::Do not use `len(SEQUENCE)` without com
use-implicit-booleaness-not-len:7:3:7:18::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
use-implicit-booleaness-not-len:11:9:11:34::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
use-implicit-booleaness-not-len:14:11:14:22::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:55:5:55:16::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:60:5:60:20::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:63:6:63:17::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:66:6:66:21::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:69:12:69:23::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:72:6:72:21::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:95:11:95:20:github_issue_1331_v2:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:98:11:98:20:github_issue_1331_v3:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:101:17:101:26:github_issue_1331_v4:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:103:9:103:15::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:104:9:104:20::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:123:11:123:34:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:124:11:124:39:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:125:11:125:24:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:126:11:126:35:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:127:11:127:33:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:128:11:128:41:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:129:11:129:43:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-use-implicit-booleaness-not-len:170:11:170:42:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
-undefined-variable:182:11:182:24:github_issue_4215:Undefined variable 'undefined_var':UNDEFINED
-undefined-variable:184:11:184:25:github_issue_4215:Undefined variable 'undefined_var2':UNDEFINED
+comparison-of-constants:39:3:39:28::"Comparison between constants: '0 < 1' has a constant value":HIGH
+use-implicit-booleaness-not-len:56:5:56:16::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:61:5:61:20::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:64:6:64:17::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:67:6:67:21::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:70:12:70:23::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:73:6:73:21::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:96:11:96:20:github_issue_1331_v2:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:99:11:99:20:github_issue_1331_v3:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:102:17:102:26:github_issue_1331_v4:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:104:9:104:15::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:105:9:105:20::Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:124:11:124:34:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:125:11:125:39:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:126:11:126:24:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:127:11:127:35:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:128:11:128:33:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:129:11:129:41:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:130:11:130:43:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+use-implicit-booleaness-not-len:171:11:171:42:github_issue_1879:Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty:UNDEFINED
+undefined-variable:183:11:183:24:github_issue_4215:Undefined variable 'undefined_var':UNDEFINED
+undefined-variable:185:11:185:25:github_issue_4215:Undefined variable 'undefined_var2':UNDEFINED
diff --git a/tests/functional/u/useless/useless_else_on_loop.py b/tests/functional/u/useless/useless_else_on_loop.py
index c7d901663..3431513cd 100644
--- a/tests/functional/u/useless/useless_else_on_loop.py
+++ b/tests/functional/u/useless/useless_else_on_loop.py
@@ -62,9 +62,9 @@ def test_break_in_orelse_deep():
"""no false positive for break in else deeply nested
"""
for _ in range(10):
- if 1 < 2:
+ if 1 < 2: # pylint: disable=comparison-of-constants
for _ in range(3):
- if 3 < 2:
+ if 3 < 2: # pylint: disable=comparison-of-constants
break
else:
break
@@ -78,9 +78,9 @@ def test_break_in_orelse_deep2():
for the inner for loop
"""
for _ in range(10):
- if 1 < 2:
+ if 1 < 2: # pylint: disable=comparison-of-constants
for _ in range(3):
- if 3 < 2:
+ if 3 < 2: # pylint: disable=comparison-of-constants
break
else:
print("all right")
@@ -96,7 +96,7 @@ def test_break_in_orelse_deep3():
for _ in range(3):
pass
else:
- if 1 < 2:
+ if 1 < 2: # pylint: disable=comparison-of-constants
break
else:
return True
diff --git a/tests/functional/u/using_constant_test.py b/tests/functional/u/using_constant_test.py
index 9b62667b7..78974681e 100644
--- a/tests/functional/u/using_constant_test.py
+++ b/tests/functional/u/using_constant_test.py
@@ -114,7 +114,7 @@ if not 3:
if instance.method():
pass
-if 2 < 3:
+if 2 < 3: # [comparison-of-constants]
pass
if tuple((1, 2, 3)):
diff --git a/tests/functional/u/using_constant_test.txt b/tests/functional/u/using_constant_test.txt
index df53a28a4..3bf09b95b 100644
--- a/tests/functional/u/using_constant_test.txt
+++ b/tests/functional/u/using_constant_test.txt
@@ -24,3 +24,4 @@ using-constant-test:84:0:None:None:test_comprehensions:Using a conditional state
using-constant-test:85:0:None:None:test_comprehensions:Using a conditional statement with a constant value:UNDEFINED
using-constant-test:89:0:90:8::Using a conditional statement with a constant value:UNDEFINED
using-constant-test:93:0:94:8::Using a conditional statement with a constant value:UNDEFINED
+comparison-of-constants:117:3:117:8::"Comparison between constants: '2 < 3' has a constant value":HIGH