diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2022-03-25 07:37:16 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-25 12:37:16 +0100 |
commit | 175dadf1948969cf78cae6e5e13a6823d74c8c4c (patch) | |
tree | 89bd8a4c8ecf41dff052a507eccd1347095adef3 /pylint | |
parent | 343d8a8fe097ea34ace6828df4a9bf2a3edd5052 (diff) | |
download | pylint-git-175dadf1948969cf78cae6e5e13a6823d74c8c4c.tar.gz |
Fix false positive for `unused-argument` where nested function uses parent argument as a `nonlocal` (#5906)
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Diffstat (limited to 'pylint')
-rw-r--r-- | pylint/checkers/variables.py | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 08acaefb8..15fa5008b 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -16,6 +16,8 @@ from typing import ( Any, DefaultDict, Dict, + Iterable, + Iterator, List, NamedTuple, Optional, @@ -343,7 +345,9 @@ def _import_name_is_global(stmt, global_names): return False -def _flattened_scope_names(iterator): +def _flattened_scope_names( + iterator: Iterator[Union[nodes.Global, nodes.Nonlocal]] +) -> Set[str]: values = (set(stmt.names) for stmt in iterator) return set(itertools.chain.from_iterable(values)) @@ -2271,7 +2275,9 @@ class VariablesChecker(BaseChecker): if not elements: self.add_message("undefined-loop-variable", args=node.name, node=node) - def _check_is_unused(self, name, node, stmt, global_names, nonlocal_names): + def _check_is_unused( + self, name, node, stmt, global_names, nonlocal_names: Iterable[str] + ): # Ignore some special names specified by user configuration. if self._is_name_ignored(stmt, name): return @@ -2293,7 +2299,7 @@ class VariablesChecker(BaseChecker): argnames = node.argnames() # Care about functions with unknown argument (builtins) if name in argnames: - self._check_unused_arguments(name, node, stmt, argnames) + self._check_unused_arguments(name, node, stmt, argnames, nonlocal_names) else: if stmt.parent and isinstance( stmt.parent, (nodes.Assign, nodes.AnnAssign, nodes.Tuple) @@ -2360,7 +2366,9 @@ class VariablesChecker(BaseChecker): regex = authorized_rgx return regex and regex.match(name) - def _check_unused_arguments(self, name, node, stmt, argnames): + def _check_unused_arguments( + self, name, node, stmt, argnames, nonlocal_names: Iterable[str] + ): is_method = node.is_method() klass = node.parent.frame(future=True) if is_method and isinstance(klass, nodes.ClassDef): @@ -2401,6 +2409,9 @@ class VariablesChecker(BaseChecker): if utils.is_protocol_class(klass): return + if name in nonlocal_names: + return + self.add_message("unused-argument", args=name, node=stmt, confidence=confidence) def _check_late_binding_closure(self, node: nodes.Name) -> None: |