summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDani Alcala <112832187+clavedeluna@users.noreply.github.com>2022-11-13 11:56:38 -0300
committerGitHub <noreply@github.com>2022-11-13 14:56:38 +0000
commit80a9d4a82e1297fbb110c9f4726eb4aa9b65ef61 (patch)
tree8bc787ad6af1482d78cfc2b3f615704921491052
parent131b315fe6c70f171501fa75b45d7062b3428d73 (diff)
downloadpylint-git-80a9d4a82e1297fbb110c9f4726eb4aa9b65ef61.tar.gz
Flag `superfluous-parens` if parentheses are used during string concatenation (#7752)
-rw-r--r--doc/whatsnew/fragments/4792.false_negative3
-rw-r--r--pylint/checkers/format.py2
-rw-r--r--tests/functional/a/alternative/alternative_union_syntax.py2
-rw-r--r--tests/functional/i/implicit/implicit_str_concat.py2
-rw-r--r--tests/functional/i/invalid/invalid_all_format.py2
-rw-r--r--tests/functional/i/invalid/invalid_all_format.txt1
-rw-r--r--tests/functional/s/slots_checks.py2
-rw-r--r--tests/functional/s/slots_checks.txt1
-rw-r--r--tests/functional/s/superfluous_parens.py20
-rw-r--r--tests/functional/s/superfluous_parens.txt6
-rw-r--r--tests/functional/s/superfluous_parens_walrus_py38.py24
-rw-r--r--tests/functional/s/superfluous_parens_walrus_py38.txt5
12 files changed, 58 insertions, 12 deletions
diff --git a/doc/whatsnew/fragments/4792.false_negative b/doc/whatsnew/fragments/4792.false_negative
new file mode 100644
index 000000000..6d05ef565
--- /dev/null
+++ b/doc/whatsnew/fragments/4792.false_negative
@@ -0,0 +1,3 @@
+Flag ``superfluous-parens`` if parentheses are used during string concatenation.
+
+Closes #4792
diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py
index 247385f2a..cde34b5d7 100644
--- a/pylint/checkers/format.py
+++ b/pylint/checkers/format.py
@@ -55,6 +55,8 @@ _KEYWORD_TOKENS = {
"while",
"yield",
"with",
+ "=",
+ ":=",
}
_JUNK_TOKENS = {tokenize.COMMENT, tokenize.NL}
diff --git a/tests/functional/a/alternative/alternative_union_syntax.py b/tests/functional/a/alternative/alternative_union_syntax.py
index 4492323a2..d25d9e8f4 100644
--- a/tests/functional/a/alternative/alternative_union_syntax.py
+++ b/tests/functional/a/alternative/alternative_union_syntax.py
@@ -1,6 +1,6 @@
"""Test PEP 604 - Alternative Union syntax"""
# pylint: disable=missing-function-docstring,unused-argument,invalid-name,missing-class-docstring
-# pylint: disable=inherit-non-class,too-few-public-methods,unnecessary-direct-lambda-call
+# pylint: disable=inherit-non-class,too-few-public-methods,unnecessary-direct-lambda-call,superfluous-parens
import dataclasses
import typing
from dataclasses import dataclass
diff --git a/tests/functional/i/implicit/implicit_str_concat.py b/tests/functional/i/implicit/implicit_str_concat.py
index 920b29258..7e28b4cc2 100644
--- a/tests/functional/i/implicit/implicit_str_concat.py
+++ b/tests/functional/i/implicit/implicit_str_concat.py
@@ -1,4 +1,4 @@
-# pylint: disable=invalid-name, missing-docstring, redundant-u-string-prefix, line-too-long
+# pylint: disable=invalid-name, missing-docstring, redundant-u-string-prefix, line-too-long, superfluous-parens
# Basic test with a list
TEST_LIST1 = ['a' 'b'] # [implicit-str-concat]
diff --git a/tests/functional/i/invalid/invalid_all_format.py b/tests/functional/i/invalid/invalid_all_format.py
index 1d1c0b18f..10537c6fb 100644
--- a/tests/functional/i/invalid/invalid_all_format.py
+++ b/tests/functional/i/invalid/invalid_all_format.py
@@ -2,6 +2,6 @@
Tuples with one element MUST contain a comma! Otherwise it's a string.
"""
-__all__ = ("CONST") # [invalid-all-format]
+__all__ = ("CONST") # [invalid-all-format, superfluous-parens]
CONST = 42
diff --git a/tests/functional/i/invalid/invalid_all_format.txt b/tests/functional/i/invalid/invalid_all_format.txt
index 2ba8dc17f..2f6ac363b 100644
--- a/tests/functional/i/invalid/invalid_all_format.txt
+++ b/tests/functional/i/invalid/invalid_all_format.txt
@@ -1 +1,2 @@
invalid-all-format:5:11:None:None::Invalid format for __all__, must be tuple or list:UNDEFINED
+superfluous-parens:5:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
diff --git a/tests/functional/s/slots_checks.py b/tests/functional/s/slots_checks.py
index e8d55d967..2c22e968e 100644
--- a/tests/functional/s/slots_checks.py
+++ b/tests/functional/s/slots_checks.py
@@ -64,7 +64,7 @@ class SixthBad: # [single-string-used-for-slots]
__slots__ = "a"
class SeventhBad: # [single-string-used-for-slots]
- __slots__ = ('foo')
+ __slots__ = ('foo') # [superfluous-parens]
class EighthBad: # [single-string-used-for-slots]
__slots__ = deque.__name__
diff --git a/tests/functional/s/slots_checks.txt b/tests/functional/s/slots_checks.txt
index 3abccff8f..d63ad2517 100644
--- a/tests/functional/s/slots_checks.txt
+++ b/tests/functional/s/slots_checks.txt
@@ -5,6 +5,7 @@ invalid-slots:57:0:57:15:FourthBad:Invalid __slots__ object:UNDEFINED
invalid-slots-object:61:27:61:29:FifthBad:"Invalid object ""''"" in __slots__, must contain only non empty strings":INFERENCE
single-string-used-for-slots:63:0:63:14:SixthBad:Class __slots__ should be a non-string iterable:UNDEFINED
single-string-used-for-slots:66:0:66:16:SeventhBad:Class __slots__ should be a non-string iterable:UNDEFINED
+superfluous-parens:67:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
single-string-used-for-slots:69:0:69:15:EighthBad:Class __slots__ should be a non-string iterable:UNDEFINED
invalid-slots-object:73:17:73:20:NinthBad:Invalid object 'str' in __slots__, must contain only non empty strings:INFERENCE
invalid-slots-object:76:17:76:26:TenthBad:Invalid object '1 + 2 + 3' in __slots__, must contain only non empty strings:INFERENCE
diff --git a/tests/functional/s/superfluous_parens.py b/tests/functional/s/superfluous_parens.py
index db9349cce..35acfd5d3 100644
--- a/tests/functional/s/superfluous_parens.py
+++ b/tests/functional/s/superfluous_parens.py
@@ -47,13 +47,6 @@ def function_B(var):
def function_C(first, second):
return (first or second) in (0, 1)
-# TODO: Test string combinations, see https://github.com/PyCQA/pylint/issues/4792
-# The lines with "+" should raise the superfluous-parens message
-J = "TestString"
-K = ("Test " + "String")
-L = ("Test " + "String") in I
-assert "" + ("Version " + "String") in I
-
# Test numpy
def function_numpy_A(var_1: int, var_2: int) -> np.ndarray:
result = (((var_1 & var_2)) > 0)
@@ -72,6 +65,19 @@ class ClassA:
if (A == 2) is not (B == 2):
pass
+K = ("Test " + "String") # [superfluous-parens]
M = A is not (A <= H)
M = True is not (M == K)
M = True is not (True is not False) # pylint: disable=comparison-of-constants
+
+Z = "TestString"
+X = ("Test " + "String") # [superfluous-parens]
+Y = ("Test " + "String") in Z # [superfluous-parens]
+assert ("Test " + "String") in "hello" # [superfluous-parens]
+assert ("Version " + "String") in ("Version " + "String") # [superfluous-parens]
+
+hi = ("CONST") # [superfluous-parens]
+hi = ("CONST",)
+
+#TODO: maybe get this line to report [superfluous-parens] without causing other false positives.
+assert "" + ("Version " + "String") in Z
diff --git a/tests/functional/s/superfluous_parens.txt b/tests/functional/s/superfluous_parens.txt
index f830922bc..08b2dd390 100644
--- a/tests/functional/s/superfluous_parens.txt
+++ b/tests/functional/s/superfluous_parens.txt
@@ -4,3 +4,9 @@ superfluous-parens:12:0:None:None::Unnecessary parens after 'for' keyword:UNDEFI
superfluous-parens:14:0:None:None::Unnecessary parens after 'if' keyword:UNDEFINED
superfluous-parens:19:0:None:None::Unnecessary parens after 'del' keyword:UNDEFINED
superfluous-parens:31:0:None:None::Unnecessary parens after 'assert' keyword:UNDEFINED
+superfluous-parens:68:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
+superfluous-parens:74:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
+superfluous-parens:75:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
+superfluous-parens:76:0:None:None::Unnecessary parens after 'assert' keyword:UNDEFINED
+superfluous-parens:77:0:None:None::Unnecessary parens after 'assert' keyword:UNDEFINED
+superfluous-parens:79:0:None:None::Unnecessary parens after '=' keyword:UNDEFINED
diff --git a/tests/functional/s/superfluous_parens_walrus_py38.py b/tests/functional/s/superfluous_parens_walrus_py38.py
index cf155954e..43b7c2aee 100644
--- a/tests/functional/s/superfluous_parens_walrus_py38.py
+++ b/tests/functional/s/superfluous_parens_walrus_py38.py
@@ -1,5 +1,5 @@
"""Test the superfluous-parens warning with python 3.8 functionality (walrus operator)"""
-# pylint: disable=missing-function-docstring, invalid-name, missing-class-docstring, import-error
+# pylint: disable=missing-function-docstring, invalid-name, missing-class-docstring, import-error, pointless-statement
import numpy
# Test parens in if statements
@@ -49,3 +49,25 @@ class TestYieldClass:
@classmethod
def function_C(cls):
yield (1 + 1) # [superfluous-parens]
+
+
+if (x := "Test " + "String"):
+ print(x)
+
+if (x := ("Test " + "String")): # [superfluous-parens]
+ print(x)
+
+if not (foo := "Test " + "String" in "hello"):
+ print(foo)
+
+if not (foo := ("Test " + "String") in "hello"): # [superfluous-parens]
+ print(foo)
+
+assert (ret := "Test " + "String")
+assert (ret := ("Test " + "String")) # [superfluous-parens]
+
+(walrus := False)
+(walrus := (False)) # [superfluous-parens]
+
+(hi := ("CONST")) # [superfluous-parens]
+(hi := ("CONST",))
diff --git a/tests/functional/s/superfluous_parens_walrus_py38.txt b/tests/functional/s/superfluous_parens_walrus_py38.txt
index 58097f520..da8f1b999 100644
--- a/tests/functional/s/superfluous_parens_walrus_py38.txt
+++ b/tests/functional/s/superfluous_parens_walrus_py38.txt
@@ -3,3 +3,8 @@ superfluous-parens:19:0:None:None::Unnecessary parens after 'if' keyword:UNDEFIN
superfluous-parens:22:0:None:None::Unnecessary parens after 'not' keyword:UNDEFINED
superfluous-parens:25:0:None:None::Unnecessary parens after 'not' keyword:UNDEFINED
superfluous-parens:51:0:None:None::Unnecessary parens after 'yield' keyword:UNDEFINED
+superfluous-parens:57:0:None:None::"Unnecessary parens after ':=' keyword":UNDEFINED
+superfluous-parens:63:0:None:None::"Unnecessary parens after ':=' keyword":UNDEFINED
+superfluous-parens:67:0:None:None::"Unnecessary parens after ':=' keyword":UNDEFINED
+superfluous-parens:70:0:None:None::"Unnecessary parens after ':=' keyword":UNDEFINED
+superfluous-parens:72:0:None:None::"Unnecessary parens after ':=' keyword":UNDEFINED