diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2022-09-04 08:44:11 -0400 |
---|---|---|
committer | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2022-09-04 15:43:44 +0200 |
commit | 7fdde384f0d308f65ccc560a4192ffb1f1381de5 (patch) | |
tree | 1255f62f5de055a10ad8964c47bfb8eb62ea4504 | |
parent | a11a087e5da132675bbed1e4b53fcaeb11ccb960 (diff) | |
download | pylint-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_negative | 4 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 8 | ||||
-rw-r--r-- | tests/functional/u/used/used_before_assignment_nonlocal.py | 18 | ||||
-rw-r--r-- | tests/functional/u/used/used_before_assignment_nonlocal.txt | 1 |
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 |