summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2021-09-01 09:31:16 +0200
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2021-09-01 10:00:30 +0200
commit3f122e08bd1cfdf7d4c9dfa77929cb4f8f8be081 (patch)
tree85393f4a2404b521e43b76e639e9184f225e474e
parentd57931bf309e548d3b4f406c9df4df4bd514f188 (diff)
downloadpylint-git-3f122e08bd1cfdf7d4c9dfa77929cb4f8f8be081.tar.gz
Fix false positive ``superfluous-parens`` for tuples
Tuples can be created with inner tuples. This creates double parenthesis which we flagged incorrectly. This closes #4907
-rw-r--r--ChangeLog4
-rw-r--r--doc/whatsnew/2.11.rst4
-rw-r--r--pylint/checkers/format.py8
-rw-r--r--tests/checkers/unittest_format.py5
-rw-r--r--tests/functional/s/super/superfluous_parens.py33
-rw-r--r--tests/functional/s/super/superfluous_parens.txt16
6 files changed, 43 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index c895b9dff..ee1b82af5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -59,6 +59,10 @@ Release date: TBA
Closes #4945
+* Fix false positive ``superfluous-parens`` for tuples created with inner tuples
+
+ Closes #4907
+
What's New in Pylint 2.10.3?
============================
diff --git a/doc/whatsnew/2.11.rst b/doc/whatsnew/2.11.rst
index 6a22d5ba7..cdbba865d 100644
--- a/doc/whatsnew/2.11.rst
+++ b/doc/whatsnew/2.11.rst
@@ -65,3 +65,7 @@ Other Changes
and ``pathlib.Path().write_text()``
Closes #4945
+
+* Fix false positive ``superfluous-parens`` for tuples created with inner tuples
+
+ Closes #4907
diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py
index 901259c3a..1306070ba 100644
--- a/pylint/checkers/format.py
+++ b/pylint/checkers/format.py
@@ -401,11 +401,11 @@ class FormatChecker(BaseTokenChecker):
depth -= 1
if depth:
if contains_double_parens and tokens[i + 1].string == ")":
- self.add_message(
- "superfluous-parens", line=line_num, args=keyword_token
- )
+ # For walrus operators in `if (not)` conditions and comprehensions
+ if keyword_token in {"in", "if", "not"}:
+ continue
return
- contains_double_parens = 0
+ contains_double_parens -= 1
continue
# ')' can't happen after if (foo), since it would be a syntax error.
if tokens[i + 1].string in (":", ")", "]", "}", "in") or tokens[
diff --git a/tests/checkers/unittest_format.py b/tests/checkers/unittest_format.py
index b84ce4438..658a7e3f4 100644
--- a/tests/checkers/unittest_format.py
+++ b/tests/checkers/unittest_format.py
@@ -165,11 +165,6 @@ class TestSuperfluousParentheses(CheckerTestCase):
(Message("superfluous-parens", line=1, args="if"), "if (foo):", 0),
(Message("superfluous-parens", line=1, args="if"), "if ((foo, bar)):", 0),
(Message("superfluous-parens", line=1, args="if"), "if (foo(bar)):", 0),
- (
- Message("superfluous-parens", line=1, args="return"),
- "return ((x for x in x))",
- 0,
- ),
(Message("superfluous-parens", line=1, args="not"), "not (foo)", 0),
(Message("superfluous-parens", line=1, args="not"), "if not (foo):", 1),
(Message("superfluous-parens", line=1, args="if"), "if (not (foo)):", 0),
diff --git a/tests/functional/s/super/superfluous_parens.py b/tests/functional/s/super/superfluous_parens.py
index aea4b16c4..ad36583f9 100644
--- a/tests/functional/s/super/superfluous_parens.py
+++ b/tests/functional/s/super/superfluous_parens.py
@@ -1,6 +1,7 @@
"""Test the superfluous-parens warning."""
-from __future__ import print_function
# pylint: disable=unneeded-not, unnecessary-comprehension, missing-function-docstring, invalid-name, fixme
+# pylint: disable=import-error, missing-class-docstring, too-few-public-methods
+import numpy as np
A = 3
if (A == 5): # [superfluous-parens]
pass
@@ -18,10 +19,10 @@ DICT = {'a': 1, 'b': 2}
del(DICT['b']) # [superfluous-parens]
del DICT['a']
-B = [x for x in ((3, 4))] # [superfluous-parens]
+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)))] # [superfluous-parens]
-E = [x for x in ((3, 4) if 1 > 0 else ((((5, 6)))))] # [superfluous-parens]
+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)))))]
# Test assertions
F = "Version 1.0"
@@ -34,14 +35,30 @@ H = 2 + (5 * 3)
NUMS_LIST = ['1', '2', '3']
NUMS_SET = {'1', '2', '3'}
NUMS_DICT = {'1': 1, '2': 2, '3': 3}
+I = tuple(x for x in ((a, str(a)) for a in ()))
# Test functions
def function_A():
- return (x for x in ((3, 4))) # [superfluous-parens]
+ return (x for x in ((3, 4)))
# TODO: Test string combinations, see https://github.com/PyCQA/pylint/issues/4792
# Lines 45, 46 & 47 should raise the superfluous-parens message
-I = "TestString"
-J = ("Test " + "String")
-K = ("Test " + "String") in I
+J = "TestString"
+K = ("Test " + "String")
+L = ("Test " + "String") in I
assert "" + ("Version " + "String") in I
+
+# Test numpy
+def function_B(var_1: int, var_2: int) -> np.ndarray:
+ result = (((var_1 & var_2)) > 0)
+ return result.astype(np.float32)
+
+def function_C(var_1: int, var_2: int) -> np.ndarray:
+ return (((var_1 & var_2)) > 0).astype(np.float32)
+
+# Test Class
+class ClassA:
+ keys = []
+
+ def __iter__(self):
+ return ((k, getattr(self, k)) for k in self.keys)
diff --git a/tests/functional/s/super/superfluous_parens.txt b/tests/functional/s/super/superfluous_parens.txt
index 0afe7635d..d07817e3d 100644
--- a/tests/functional/s/super/superfluous_parens.txt
+++ b/tests/functional/s/super/superfluous_parens.txt
@@ -1,10 +1,6 @@
-superfluous-parens:5:0::Unnecessary parens after 'if' keyword:HIGH
-superfluous-parens:7:0::Unnecessary parens after 'not' keyword:HIGH
-superfluous-parens:11:0::Unnecessary parens after 'for' keyword:HIGH
-superfluous-parens:13:0::Unnecessary parens after 'if' keyword:HIGH
-superfluous-parens:18:0::Unnecessary parens after 'del' keyword:HIGH
-superfluous-parens:21:0::Unnecessary parens after 'in' keyword:HIGH
-superfluous-parens:23:0::Unnecessary parens after 'else' keyword:HIGH
-superfluous-parens:24:0::Unnecessary parens after 'else' keyword:HIGH
-superfluous-parens:30:0::Unnecessary parens after 'assert' keyword:HIGH
-superfluous-parens:40:0::Unnecessary parens after 'in' keyword:HIGH
+superfluous-parens:6:0::Unnecessary parens after 'if' keyword:HIGH
+superfluous-parens:8:0::Unnecessary parens after 'not' keyword:HIGH
+superfluous-parens:12:0::Unnecessary parens after 'for' keyword:HIGH
+superfluous-parens:14:0::Unnecessary parens after 'if' keyword:HIGH
+superfluous-parens:19:0::Unnecessary parens after 'del' keyword:HIGH
+superfluous-parens:31:0::Unnecessary parens after 'assert' keyword:HIGH