summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2022-09-04 08:44:11 -0400
committerDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2022-09-04 15:43:44 +0200
commit7fdde384f0d308f65ccc560a4192ffb1f1381de5 (patch)
tree1255f62f5de055a10ad8964c47bfb8eb62ea4504
parenta11a087e5da132675bbed1e4b53fcaeb11ccb960 (diff)
downloadpylint-git-7fdde384f0d308f65ccc560a4192ffb1f1381de5.tar.gz
Emit `used-before-assignment` when function arguments are redefined inside an inner function
-rw-r--r--doc/whatsnew/fragments/2374.false_negative4
-rw-r--r--pylint/checkers/utils.py8
-rw-r--r--tests/functional/u/used/used_before_assignment_nonlocal.py18
-rw-r--r--tests/functional/u/used/used_before_assignment_nonlocal.txt1
4 files changed, 31 insertions, 0 deletions
diff --git a/doc/whatsnew/fragments/2374.false_negative b/doc/whatsnew/fragments/2374.false_negative
new file mode 100644
index 000000000..251ffc396
--- /dev/null
+++ b/doc/whatsnew/fragments/2374.false_negative
@@ -0,0 +1,4 @@
+Emit ``used-before-assignment`` when function arguments are redefined inside
+an inner function and accessed there before assignment.
+
+Closes #2374
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index 68452db0e..561b8b7a5 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -357,6 +357,14 @@ def is_defined_before(var_node: nodes.Name) -> bool:
continue
defnode_scope = defnode.scope()
if isinstance(defnode_scope, COMP_NODE_TYPES + (nodes.Lambda,)):
+ # Avoid the case where var_node_scope is a nested function
+ # FunctionDef is a Lambda until https://github.com/PyCQA/astroid/issues/291
+ if isinstance(defnode_scope, nodes.FunctionDef):
+ var_node_scope = var_node.scope()
+ if var_node_scope is not defnode_scope and isinstance(
+ var_node_scope, nodes.FunctionDef
+ ):
+ return False
return True
if defnode.lineno < var_node.lineno:
return True
diff --git a/tests/functional/u/used/used_before_assignment_nonlocal.py b/tests/functional/u/used/used_before_assignment_nonlocal.py
index 270b72d22..18e16177d 100644
--- a/tests/functional/u/used/used_before_assignment_nonlocal.py
+++ b/tests/functional/u/used/used_before_assignment_nonlocal.py
@@ -88,3 +88,21 @@ def type_annotation_never_gets_value_despite_nonlocal():
nonlocal some_num
inner()
print(some_num) # [used-before-assignment]
+
+
+def inner_function_lacks_access_to_outer_args(args):
+ """Check homonym between inner function and outer function names"""
+ def inner():
+ print(args) # [used-before-assignment]
+ args = []
+ inner()
+ print(args)
+
+
+def inner_function_ok(args):
+ """Explicitly redefined homonym defined before is OK."""
+ def inner():
+ args = []
+ print(args)
+ inner()
+ print(args)
diff --git a/tests/functional/u/used/used_before_assignment_nonlocal.txt b/tests/functional/u/used/used_before_assignment_nonlocal.txt
index 3e5045f27..2bdbf2fe1 100644
--- a/tests/functional/u/used/used_before_assignment_nonlocal.txt
+++ b/tests/functional/u/used/used_before_assignment_nonlocal.txt
@@ -5,3 +5,4 @@ used-before-assignment:33:22:33:32:test_fail4:Using variable 'test_fail5' before
used-before-assignment:33:44:33:53:test_fail4:Using variable 'undefined' before assignment:HIGH
used-before-assignment:39:18:39:28:test_fail5:Using variable 'undefined1' before assignment:HIGH
used-before-assignment:90:10:90:18:type_annotation_never_gets_value_despite_nonlocal:Using variable 'some_num' before assignment:HIGH
+used-before-assignment:96:14:96:18:inner_function_lacks_access_to_outer_args.inner:Using variable 'args' before assignment:HIGH