diff options
author | Marc Mueller <30130371+cdce8p@users.noreply.github.com> | 2021-02-03 01:08:14 +0100 |
---|---|---|
committer | Pierre Sassoulas <pierre.sassoulas@gmail.com> | 2021-02-15 16:16:27 +0100 |
commit | 1282688abc6284124f9c3163838cdfa1d7f60f62 (patch) | |
tree | d835cfd621cf7f1ca37dcca8f4c26acf0d865260 | |
parent | 1175b6e9110d2319a3cb4d4e8481b774b6a3cbb9 (diff) | |
download | pylint-git-1282688abc6284124f9c3163838cdfa1d7f60f62.tar.gz |
Fix multiple false positives with assignment expressions
* Used-before-assignment false positive
* Undefined-variable false positive
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 30 | ||||
-rw-r--r-- | tests/functional/a/assignment_expression.py | 58 | ||||
-rw-r--r-- | tests/functional/a/assignment_expression.rc | 2 | ||||
-rw-r--r-- | tests/functional/a/assignment_expression.txt | 3 |
5 files changed, 97 insertions, 0 deletions
@@ -39,6 +39,10 @@ Pylint's ChangeLog Closes #4065 +* Fix multiple false positives with assignment expressions + + Closes #3347, #3953, #3865, #3275 + What's New in Pylint 2.6.1? =========================== Release date: TBA diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 986f76fd2..5c3380c9d 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1407,6 +1407,36 @@ class VariablesChecker(BaseChecker): # Single statement function, with the statement on the # same line as the function definition maybee0601 = False + elif ( + isinstance(defstmt, astroid.Assign) + and isinstance(defstmt.value, astroid.IfExp) + and frame is defframe + and defframe.parent_of(node) + and stmt is defstmt + ): + # Single statement if, with assingment expression on same + # line as assigment + # x = b if (b := True) else False + maybee0601 = False + elif ( + isinstance( # pylint: disable=too-many-boolean-expressions + defnode, astroid.NamedExpr + ) + and frame is defframe + and defframe.parent_of(stmt) + and stmt is defstmt + and ( + ( + defnode.lineno == node.lineno + and defnode.col_offset < node.col_offset + ) + or (defnode.lineno < node.lineno) + ) + ): + # Expressions, with assignment expressions + # Use only after assignment + # b = (c := 2) and c + maybee0601 = False # Look for type checking definitions inside a type checking guard. if isinstance(defstmt, (astroid.Import, astroid.ImportFrom)): diff --git a/tests/functional/a/assignment_expression.py b/tests/functional/a/assignment_expression.py new file mode 100644 index 000000000..ed8400163 --- /dev/null +++ b/tests/functional/a/assignment_expression.py @@ -0,0 +1,58 @@ +"""Test assignment expressions""" +# pylint: disable=missing-docstring,unused-argument,unused-import,invalid-name,blacklisted-name,unused-variable +import re + +if (a := True): + x = a +else: + x = False + +x = b if (b := True) else False + +a = ["a ", "b ", "c "] +c = [text for el in a if (text := el.strip()) == "b"] + + +# https://github.com/PyCQA/pylint/issues/3347 +s = 'foo' if (fval := lambda: 1) is None else fval + + +# https://github.com/PyCQA/pylint/issues/3953 +assert (n := 2) == 1, f"Expected 1, but got {n}" +dict({1: (o := 2)}, data=o) +assert (p := 2) == 1, \ + p + +FOO_PATT = re.compile("") +foo = m.group("foo") if (m := FOO_PATT.match("")) else False + + +# https://github.com/PyCQA/pylint/issues/3865 +if (c := lambda: 2) and c(): + print("ok") + +def func(): + print((d := lambda: 2) and d) + + +# https://github.com/PyCQA/pylint/issues/3275 +values = ( + e := 1, + f := e, +) +print(values) + +function = lambda: ( + h := 1, + i := h, +) +print(function()) + + +# check wrong usage +assert err_a, (err_a := 2) # [used-before-assignment] +print(err_b and (err_b := 2)) # [used-before-assignment] +values = ( + err_c := err_d, # [used-before-assignment] + err_d := 2, +) diff --git a/tests/functional/a/assignment_expression.rc b/tests/functional/a/assignment_expression.rc new file mode 100644 index 000000000..85fc502b3 --- /dev/null +++ b/tests/functional/a/assignment_expression.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.8 diff --git a/tests/functional/a/assignment_expression.txt b/tests/functional/a/assignment_expression.txt new file mode 100644 index 000000000..df472fdd2 --- /dev/null +++ b/tests/functional/a/assignment_expression.txt @@ -0,0 +1,3 @@ +used-before-assignment:53:7::Using variable 'err_a' before assignment +used-before-assignment:54:6::Using variable 'err_b' before assignment +used-before-assignment:56:13::Using variable 'err_d' before assignment |