summaryrefslogtreecommitdiff
path: root/tests/functional
diff options
context:
space:
mode:
authorJaehoon Hwang <jaehoonhwang@users.noreply.github.com>2021-10-17 00:31:34 -0700
committerGitHub <noreply@github.com>2021-10-17 09:31:34 +0200
commit59d2b545b557a7ac47955c65935889e296da941a (patch)
treea07b8d66954e630e5b8181d175fff60c423b93c7 /tests/functional
parent9098c6078551e2d3028fe65537d3b0e407c85724 (diff)
downloadpylint-git-59d2b545b557a7ac47955c65935889e296da941a.tar.gz
Add a warning ``use-implicit-booleaness-not-comparison`` for comparison with collection literals (#5120)
* Create a new checker; use-implicit-booleanness checker where it looks for boolean evaluatiion with collection literals such as `()`, `[]`, or `{}` * Fixed invalid usage of comparison within pylint package This closes #4774 * Ignore tuples when checking for `literal-comparison` Closes #3031 * Merge len_checker with empty_literal checker Moving empty literal checker with len_checker to avoid class without iterators without boolean expressions (false positive on pandas) Reference: https://github.com/PyCQA/pylint/pull/3821/files * Update `len_checker` and its class `LenChecker` to `ComparisonChecker` to reflect better usage after merging between `len_checker` and `empty_literal_checker` and its tests. * Fixed `consider_using_in` and `consider_iterating_dictionary` tests that were failing due to new empty literal checkers. Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Diffstat (limited to 'tests/functional')
-rw-r--r--tests/functional/c/consider/consider_iterating_dictionary.py2
-rw-r--r--tests/functional/c/consider/consider_using_in.py2
-rw-r--r--tests/functional/c/consider/consider_using_in.txt28
-rw-r--r--tests/functional/l/literal_comparison.py9
-rw-r--r--tests/functional/l/literal_comparison.txt25
-rw-r--r--tests/functional/u/use/use_implicit_booleaness_not_comparison.py142
-rw-r--r--tests/functional/u/use/use_implicit_booleaness_not_comparison.txt24
7 files changed, 202 insertions, 30 deletions
diff --git a/tests/functional/c/consider/consider_iterating_dictionary.py b/tests/functional/c/consider/consider_iterating_dictionary.py
index 996fa5429..d3cc75f4d 100644
--- a/tests/functional/c/consider/consider_iterating_dictionary.py
+++ b/tests/functional/c/consider/consider_iterating_dictionary.py
@@ -1,6 +1,6 @@
# pylint: disable=missing-docstring, expression-not-assigned, too-few-public-methods
# pylint: disable=no-member, import-error, no-self-use, line-too-long, useless-object-inheritance
-# pylint: disable=unnecessary-comprehension, use-dict-literal
+# pylint: disable=unnecessary-comprehension, use-dict-literal, use-implicit-booleaness-not-comparison
from unknown import Unknown
diff --git a/tests/functional/c/consider/consider_using_in.py b/tests/functional/c/consider/consider_using_in.py
index 8d23bb093..7ce5dd0b6 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, misplaced-comparison-constant, undefined-variable, literal-comparison, line-too-long, unneeded-not, too-few-public-methods
+# pylint: disable=missing-docstring, invalid-name, pointless-statement, misplaced-comparison-constant, undefined-variable, literal-comparison, line-too-long, unneeded-not, too-few-public-methods, use-implicit-booleaness-not-comparison
value = value1 = 1
value2 = 2
diff --git a/tests/functional/c/consider/consider_using_in.txt b/tests/functional/c/consider/consider_using_in.txt
index 72c8e389d..427c0ee04 100644
--- a/tests/functional/c/consider/consider_using_in.txt
+++ b/tests/functional/c/consider/consider_using_in.txt
@@ -1,14 +1,14 @@
-consider-using-in:10:0::"Consider merging these comparisons with ""in"" to 'value in (1,)'"
-consider-using-in:11:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'"
-consider-using-in:12:0::"Consider merging these comparisons with ""in"" to ""value in ('value',)"""
-consider-using-in:13:0::"Consider merging these comparisons with ""in"" to 'value in (1, undef_value)'"
-consider-using-in:14:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2, 3)'"
-consider-using-in:15:0::"Consider merging these comparisons with ""in"" to ""value in ('2', 1)"""
-consider-using-in:16:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'"
-consider-using-in:17:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'"
-consider-using-in:18:0::"Consider merging these comparisons with ""in"" to 'value in (1, a_list)'"
-consider-using-in:19:0::"Consider merging these comparisons with ""in"" to 'value in (a_set, a_list, a_str)'"
-consider-using-in:20:0::"Consider merging these comparisons with ""in"" to 'value not in (1, 2)'"
-consider-using-in:21:0::"Consider merging these comparisons with ""in"" to 'value1 in (value2,)'"
-consider-using-in:22:0::"Consider merging these comparisons with ""in"" to 'a_list in ([1, 2, 3], [])'"
-consider-using-in:53:0::"Consider merging these comparisons with ""in"" to 'A.value in (1, 2)'"
+consider-using-in:10:0::"Consider merging these comparisons with ""in"" to 'value in (1,)'":HIGH
+consider-using-in:11:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'":HIGH
+consider-using-in:12:0::"Consider merging these comparisons with ""in"" to ""value in ('value',)""":HIGH
+consider-using-in:13:0::"Consider merging these comparisons with ""in"" to 'value in (1, undef_value)'":HIGH
+consider-using-in:14:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2, 3)'":HIGH
+consider-using-in:15:0::"Consider merging these comparisons with ""in"" to ""value in ('2', 1)""":HIGH
+consider-using-in:16:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'":HIGH
+consider-using-in:17:0::"Consider merging these comparisons with ""in"" to 'value in (1, 2)'":HIGH
+consider-using-in:18:0::"Consider merging these comparisons with ""in"" to 'value in (1, a_list)'":HIGH
+consider-using-in:19:0::"Consider merging these comparisons with ""in"" to 'value in (a_set, a_list, a_str)'":HIGH
+consider-using-in:20:0::"Consider merging these comparisons with ""in"" to 'value not in (1, 2)'":HIGH
+consider-using-in:21:0::"Consider merging these comparisons with ""in"" to 'value1 in (value2,)'":HIGH
+consider-using-in:22:0::"Consider merging these comparisons with ""in"" to 'a_list in ([1, 2, 3], [])'":HIGH
+consider-using-in:53:0::"Consider merging these comparisons with ""in"" to 'A.value in (1, 2)'":HIGH
diff --git a/tests/functional/l/literal_comparison.py b/tests/functional/l/literal_comparison.py
index 646e57eec..4e41caaa4 100644
--- a/tests/functional/l/literal_comparison.py
+++ b/tests/functional/l/literal_comparison.py
@@ -10,7 +10,7 @@ if "a" is b"a": # [literal-comparison]
if 2.0 is 3.0: # [literal-comparison]
pass
-if () is (1, 2, 3): # [literal-comparison]
+if () is (1, 2, 3):
pass
if () is {1:2, 2:3}: # [literal-comparison]
@@ -48,3 +48,10 @@ if CONST is 42: # [literal-comparison]
# object might be used as a sentinel.
if () is CONST:
pass
+
+def github_issue_3031(arg=()):
+ if arg is ():
+ pass
+
+ if arg is not ():
+ pass
diff --git a/tests/functional/l/literal_comparison.txt b/tests/functional/l/literal_comparison.txt
index 541bfe515..30d54a285 100644
--- a/tests/functional/l/literal_comparison.txt
+++ b/tests/functional/l/literal_comparison.txt
@@ -1,13 +1,12 @@
-literal-comparison:4:3::Comparison to literal
-literal-comparison:7:3::Comparison to literal
-literal-comparison:10:3::Comparison to literal
-literal-comparison:13:3::Comparison to literal
-literal-comparison:16:3::Comparison to literal
-literal-comparison:19:3::Comparison to literal
-literal-comparison:22:3::Comparison to literal
-literal-comparison:25:3::Comparison to literal
-literal-comparison:28:3::Comparison to literal
-literal-comparison:31:3::Comparison to literal
-literal-comparison:38:3::Comparison to literal
-literal-comparison:41:3::Comparison to literal
-literal-comparison:44:3::Comparison to literal
+literal-comparison:4:3::Comparison to literal:HIGH
+literal-comparison:7:3::Comparison to literal:HIGH
+literal-comparison:10:3::Comparison to literal:HIGH
+literal-comparison:16:3::Comparison to literal:HIGH
+literal-comparison:19:3::Comparison to literal:HIGH
+literal-comparison:22:3::Comparison to literal:HIGH
+literal-comparison:25:3::Comparison to literal:HIGH
+literal-comparison:28:3::Comparison to literal:HIGH
+literal-comparison:31:3::Comparison to literal:HIGH
+literal-comparison:38:3::Comparison to literal:HIGH
+literal-comparison:41:3::Comparison to literal:HIGH
+literal-comparison:44:3::Comparison to literal:HIGH
diff --git a/tests/functional/u/use/use_implicit_booleaness_not_comparison.py b/tests/functional/u/use/use_implicit_booleaness_not_comparison.py
new file mode 100644
index 000000000..18ca9c370
--- /dev/null
+++ b/tests/functional/u/use/use_implicit_booleaness_not_comparison.py
@@ -0,0 +1,142 @@
+# pylint: disable=missing-docstring, missing-module-docstring, invalid-name
+# pylint: disable=too-few-public-methods, line-too-long, dangerous-default-value
+# https://github.com/PyCQA/pylint/issues/4774
+
+def github_issue_4774():
+ # Test literals
+ # https://github.com/PyCQA/pylint/issues/4774
+ good_list = []
+ if not good_list:
+ pass
+
+ bad_list = []
+ if bad_list == []: # [use-implicit-booleaness-not-comparison]
+ pass
+
+# Testing for empty literals
+empty_tuple = ()
+empty_list = []
+empty_dict = {}
+
+if empty_tuple == (): # [use-implicit-booleaness-not-comparison]
+ pass
+
+if empty_list == []: # [use-implicit-booleaness-not-comparison]
+ pass
+
+if empty_dict == {}: # [use-implicit-booleaness-not-comparison]
+ pass
+
+if () == empty_tuple: # [use-implicit-booleaness-not-comparison]
+ pass
+
+if [] == empty_list: # [use-implicit-booleaness-not-comparison]
+ pass
+
+if {} == empty_dict: # [use-implicit-booleaness-not-comparison]
+ pass
+
+def bad_tuple_return():
+ t = (1, )
+ return t == () # [use-implicit-booleaness-not-comparison]
+
+def bad_list_return():
+ b = [1]
+ return b == [] # [use-implicit-booleaness-not-comparison]
+
+def bad_dict_return():
+ c = {1: 1}
+ return c == {} # [use-implicit-booleaness-not-comparison]
+
+assert () == empty_tuple # [use-implicit-booleaness-not-comparison]
+assert [] == empty_list # [use-implicit-booleaness-not-comparison]
+assert {} != empty_dict # [use-implicit-booleaness-not-comparison]
+assert () < empty_tuple # [use-implicit-booleaness-not-comparison]
+assert [] <= empty_list # [use-implicit-booleaness-not-comparison]
+assert () > empty_tuple # [use-implicit-booleaness-not-comparison]
+assert [] >= empty_list # [use-implicit-booleaness-not-comparison]
+
+assert [] == []
+assert {} != {}
+assert () == ()
+
+d = {}
+
+if d in {}:
+ pass
+
+class NoBool:
+ def __init__(self):
+ self.a = 2
+
+class YesBool:
+ def __init__(self):
+ self.a = True
+
+ def __bool__(self):
+ return self.a
+
+
+# Should be triggered
+a = NoBool()
+if [] == a: # [use-implicit-booleaness-not-comparison]
+ pass
+
+a = YesBool()
+if a == []:
+ pass
+
+# compound test cases
+
+e = []
+f = {}
+
+if e == [] and f == {}: # [use-implicit-booleaness-not-comparison, use-implicit-booleaness-not-comparison]
+ pass
+
+
+named_fields = [0, "", "42", "forty two"]
+empty = any(field == "" for field in named_fields)
+
+something_else = NoBool()
+empty_literals = [[], {}, ()]
+is_empty = any(field == something_else for field in empty_literals)
+
+# this should work, but it doesn't since, input parameter only get the latest one, not all when inferred()
+h, i, j = 1, None, [1,2,3]
+
+def test(k):
+ print(k == {})
+
+def test_with_default(k={}):
+ print(k == {}) # [use-implicit-booleaness-not-comparison]
+ print(k == 1)
+
+test(h)
+test(i)
+test(j)
+
+test_with_default(h)
+test_with_default(i)
+test_with_default(j)
+
+# pylint: disable=import-outside-toplevel, wrong-import-position, import-error
+# Numpy has its own implementation of __bool__, but base class has list, that's why the comparison check is happening
+import numpy
+numpy_array = numpy.array([0])
+if numpy_array == []: # [use-implicit-booleaness-not-comparison]
+ print('numpy_array')
+if numpy_array != []: # [use-implicit-booleaness-not-comparison]
+ print('numpy_array')
+if numpy_array >= (): # [use-implicit-booleaness-not-comparison]
+ print('b')
+
+# pandas has its own implementations of __bool__ and is not subclass of list, dict, or tuple; that's why comparison check is not happening
+import pandas as pd
+pandas_df = pd.DataFrame()
+if pandas_df == []:
+ pass
+if pandas_df != ():
+ pass
+if pandas_df <= []:
+ print("truth value of a dataframe is ambiguous")
diff --git a/tests/functional/u/use/use_implicit_booleaness_not_comparison.txt b/tests/functional/u/use/use_implicit_booleaness_not_comparison.txt
new file mode 100644
index 000000000..1baca0b42
--- /dev/null
+++ b/tests/functional/u/use/use_implicit_booleaness_not_comparison.txt
@@ -0,0 +1,24 @@
+use-implicit-booleaness-not-comparison:13:7:github_issue_4774:'bad_list == []' can be simplified to 'bad_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:21:3::'empty_tuple == ()' can be simplified to 'empty_tuple' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:24:3::'empty_list == []' can be simplified to 'empty_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:27:3::'empty_dict == {}' can be simplified to 'empty_dict' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:30:3::'empty_tuple == ()' can be simplified to 'empty_tuple' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:33:3::'empty_list == []' can be simplified to 'empty_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:36:3::'empty_dict == {}' can be simplified to 'empty_dict' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:41:11:bad_tuple_return:'t == ()' can be simplified to 't' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:45:11:bad_list_return:'b == []' can be simplified to 'b' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:49:11:bad_dict_return:'c == {}' can be simplified to 'c' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:51:7::'empty_tuple == ()' can be simplified to 'empty_tuple' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:52:7::'empty_list == []' can be simplified to 'empty_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:53:7::'empty_dict != {}' can be simplified to 'not empty_dict' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:54:7::'empty_tuple < ()' can be simplified to 'empty_tuple' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:55:7::'empty_list <= []' can be simplified to 'empty_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:56:7::'empty_tuple > ()' can be simplified to 'empty_tuple' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:57:7::'empty_list >= []' can be simplified to 'empty_list' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:82:3::'a == []' can be simplified to 'a' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:94:3::'e == []' can be simplified to 'e' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:94:15::'f == {}' can be simplified to 'f' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:112:10:test_with_default:'k == {}' can be simplified to 'k' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:127:3::'numpy_array == []' can be simplified to 'numpy_array' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:129:3::'numpy_array != []' can be simplified to 'not numpy_array' as an empty sequence is falsey:HIGH
+use-implicit-booleaness-not-comparison:131:3::'numpy_array >= ()' can be simplified to 'numpy_array' as an empty sequence is falsey:HIGH