Skip to content

Commit

Permalink
Fix false positive superfluous parens for walrus operator
Browse files Browse the repository at this point in the history
  • Loading branch information
brycepg committed Jun 16, 2020
1 parent ba0c794 commit 3d01ba1
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Expand Up @@ -30,6 +30,11 @@ Release date: TBA

* Fix `pre-commit` config that could lead to undetected duplicate lines of code

* Fix superfluous-parens false-positive for the walrus operator

Close #3383


What's New in Pylint 2.5.3?
===========================

Expand Down
12 changes: 12 additions & 0 deletions pylint/checkers/format.py
Expand Up @@ -371,11 +371,18 @@ def _check_keyword_parentheses(self, tokens: List[TokenInfo], start: int) -> Non
if tokens[start + 1].string != "(":
return
found_and_or = False
contains_walrus_operator = False
walrus_operator_depth = 0
depth = 0
keyword_token = str(tokens[start].string)
line_num = tokens[start].start[0]
for i in range(start, len(tokens) - 1):
token = tokens[i]

if token.string == ":=":
contains_walrus_operator = True
walrus_operator_depth = depth

# If we hit a newline, then assume any parens were for continuation.
if token.type == tokenize.NL:
return
Expand All @@ -390,6 +397,11 @@ def _check_keyword_parentheses(self, tokens: List[TokenInfo], start: int) -> Non
tokens[i + 1].type in
(tokenize.NEWLINE, tokenize.ENDMARKER, tokenize.COMMENT)):
# The empty tuple () is always accepted.
if contains_walrus_operator and walrus_operator_depth - 1 == depth:
# Reset variable for possible following expressions
contains_walrus_operator = False
walrus_operator_depth = None
continue
if i == start + 2:
return
if keyword_token == "not":
Expand Down
22 changes: 22 additions & 0 deletions tests/checkers/unittest_format.py
Expand Up @@ -184,6 +184,28 @@ def testCheckKeywordParensHandlesUnnecessaryParens(self):
with self.assertAddsMessages(msg):
self.checker._check_keyword_parentheses(_tokenize_str(code), offset)

def testNoSuperfluousParensWalrusOperatorIf(self):
"""Parenthesis change the meaning of assignment in the walrus operator
and so are not superfluous:"""
code = "[odd for i in range(99) if (odd := is_odd(i))]"
offset = 0
with self.assertNoMessages():
self.checker._check_keyword_parentheses(_tokenize_str(code), offset)

def testPositiveSuperfluousParensWalrusOperatorIf(self):
"""Test positive superfluous parens with the walrus operator"""
code = "[odd for i in range(99) if ((odd := is_odd(i)))]"
offset = 0
msg = Message("superfluous-parens", line=1, args="if")
with self.assertAddsMessages(msg):
self.checker._check_keyword_parentheses(_tokenize_str(code), 0)

def testSuperfluousParensWalrusOperatorNot(self):
"""Test superfluous-parens with the not operator"""
code = "not (foo := 5)"
with self.assertNoMessages():
self.checker._check_keyword_parentheses(_tokenize_str(code), 0)

def testCheckIfArgsAreNotUnicode(self):
cases = [("if (foo):", 0), ("assert (1 == 1)", 0)]

Expand Down

0 comments on commit 3d01ba1

Please sign in to comment.