summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Mueller <30130371+cdce8p@users.noreply.github.com>2021-03-25 22:26:01 +0100
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2021-03-28 22:48:56 +0200
commit3c48f2c77ba68a3128b96fa6a98224eb6191bb4d (patch)
tree59cac9b7fdb7f4b76f4c0d6066122c803d379e5a
parentc5ad01c4865fb20af90cff241f595e5fe06e37c2 (diff)
downloadpylint-git-3c48f2c77ba68a3128b96fa6a98224eb6191bb4d.tar.gz
Improve handling of assignment expressions
-rw-r--r--ChangeLog4
-rw-r--r--pylint/checkers/variables.py23
-rw-r--r--pylint/constants.py1
-rw-r--r--tests/functional/a/assignment_expression.py21
-rw-r--r--tests/functional/a/assignment_expression.txt7
5 files changed, 52 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f9d17959..41452c7ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -61,6 +61,10 @@ Release date: TBA
Closes #4218
+* Improve handling of assignment expressions, better edge case handling
+
+ Closes #3763, #4238
+
What's New in Pylint 2.7.2?
===========================
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 3d7eadc20..f9c1f0fe4 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -59,6 +59,7 @@ from astroid.context import InferenceContext
from pylint.checkers import BaseChecker, utils
from pylint.checkers.utils import is_postponed_evaluation_enabled
+from pylint.constants import PY39_PLUS
from pylint.interfaces import HIGH, INFERENCE, INFERENCE_FAILURE, IAstroidChecker
from pylint.utils import get_global_option
@@ -1410,7 +1411,15 @@ class VariablesChecker(BaseChecker):
# same line as the function definition
maybee0601 = False
elif (
- isinstance(defstmt, astroid.Assign)
+ isinstance(
+ defstmt,
+ (
+ astroid.Assign,
+ astroid.AnnAssign,
+ astroid.AugAssign,
+ astroid.Expr,
+ ),
+ )
and isinstance(defstmt.value, astroid.IfExp)
and frame is defframe
and defframe.parent_of(node)
@@ -1433,6 +1442,18 @@ class VariablesChecker(BaseChecker):
and defnode.col_offset < node.col_offset
)
or (defnode.lineno < node.lineno)
+ or (
+ # Issue in the `ast` module until py39
+ # Nodes in a multiline string have the same lineno
+ # Could be false-positive without check
+ not PY39_PLUS
+ and defnode.lineno == node.lineno
+ and isinstance(
+ defstmt,
+ (astroid.Assign, astroid.AnnAssign, astroid.AugAssign),
+ )
+ and isinstance(defstmt.value, astroid.JoinedStr)
+ )
)
):
# Expressions, with assignment expressions
diff --git a/pylint/constants.py b/pylint/constants.py
index 929eed97e..7181cb355 100644
--- a/pylint/constants.py
+++ b/pylint/constants.py
@@ -8,6 +8,7 @@ from astroid.__pkginfo__ import version as astroid_version
from pylint.__pkginfo__ import version as pylint_version
PY38_PLUS = sys.version_info[:2] >= (3, 8)
+PY39_PLUS = sys.version_info[:2] >= (3, 9)
PY310_PLUS = sys.version_info[:2] >= (3, 10)
diff --git a/tests/functional/a/assignment_expression.py b/tests/functional/a/assignment_expression.py
index ed8400163..aa6a27874 100644
--- a/tests/functional/a/assignment_expression.py
+++ b/tests/functional/a/assignment_expression.py
@@ -8,6 +8,9 @@ else:
x = False
x = b if (b := True) else False
+x2: bool = b2 if (b2 := True) else False
+x3 = 0
+x3 += b3 if (b3 := 4) else 6
a = ["a ", "b ", "c "]
c = [text for el in a if (text := el.strip()) == "b"]
@@ -49,6 +52,24 @@ function = lambda: (
print(function())
+# https://github.com/PyCQA/pylint/issues/3763
+foo if (foo := 3 - 2) > 0 else 0 # [pointless-statement]
+
+
+# https://github.com/PyCQA/pylint/issues/4238
+l1 = f'The number {(count1 := 4)} ' \
+ f'is equal to {count1}'
+l2: str = (
+ f'The number {(count2 := 4)} '
+ f'is equal to {count2}'
+)
+l3 = "Hello "
+l3 += (
+ f'The number {(count3 := 4)} '
+ f'is equal to {count3}'
+)
+
+
# check wrong usage
assert err_a, (err_a := 2) # [used-before-assignment]
print(err_b and (err_b := 2)) # [used-before-assignment]
diff --git a/tests/functional/a/assignment_expression.txt b/tests/functional/a/assignment_expression.txt
index df472fdd2..1be4c1389 100644
--- a/tests/functional/a/assignment_expression.txt
+++ b/tests/functional/a/assignment_expression.txt
@@ -1,3 +1,4 @@
-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
+pointless-statement:56:0::Statement seems to have no effect
+used-before-assignment:74:7::Using variable 'err_a' before assignment
+used-before-assignment:75:6::Using variable 'err_b' before assignment
+used-before-assignment:77:13::Using variable 'err_d' before assignment