diff options
author | David Liu <david@cs.toronto.edu> | 2021-09-20 16:11:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-20 22:11:44 +0200 |
commit | fb750d39f82dd58342a7683ac5e03b38ba64ae4a (patch) | |
tree | ca09ea459879419a29c17e5b2a9f84b675a66b8d | |
parent | 24cbf8c33120db595c3dd9443418e1b8472839fd (diff) | |
download | pylint-git-fb750d39f82dd58342a7683ac5e03b38ba64ae4a.tar.gz |
Fix bug with cell-var-from-loop and kw_defaults (#5045)
* Fix bug with cell-var-from-loop and kw_defaults
* Use more efficient generator for defaults and add issue link
* Fix test output for cellvar_escaping_loop
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 13 | ||||
-rw-r--r-- | tests/functional/c/cellvar_escaping_loop.py | 16 | ||||
-rw-r--r-- | tests/functional/c/cellvar_escaping_loop.txt | 26 |
4 files changed, 43 insertions, 17 deletions
@@ -29,6 +29,11 @@ Release date: TBA Closes #5029 +* Fixed false positive for ``cell-var-from-loop`` when variable is used as the default + value for a keyword-only parameter. + + Closes #5012 + What's New in Pylint 2.11.1? ============================ diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 305a4fc94..87c12433d 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -402,10 +402,15 @@ def is_default_argument( if not scope: scope = node.scope() if isinstance(scope, (nodes.FunctionDef, nodes.Lambda)): - for default_node in scope.args.defaults: - for default_name_node in default_node.nodes_of_class(nodes.Name): - if default_name_node is node: - return True + all_defaults = itertools.chain( + scope.args.defaults, (d for d in scope.args.kw_defaults if d is not None) + ) + return any( + default_name_node is node + for default_node in all_defaults + for default_name_node in default_node.nodes_of_class(nodes.Name) + ) + return False diff --git a/tests/functional/c/cellvar_escaping_loop.py b/tests/functional/c/cellvar_escaping_loop.py index 5520fe949..502ec75f1 100644 --- a/tests/functional/c/cellvar_escaping_loop.py +++ b/tests/functional/c/cellvar_escaping_loop.py @@ -93,6 +93,22 @@ def good_case_issue3107(): next(filter(lambda j, ix=i[0]: j == ix, [1, 3])) +def good_case_issue_5012(): + """Eager binding of cell variable when used as the default value of a keyword-only argument. + https://github.com/PyCQA/pylint/issues/5012 + """ + funs = [] + for i in range(5): + def func(*, _i=i): + print(_i) + funs.append(func) + + def func2(_i=i): + print(_i) + funs.append(func2) + + return funs + def bad_case(): """Closing over a loop variable.""" lst = [] diff --git a/tests/functional/c/cellvar_escaping_loop.txt b/tests/functional/c/cellvar_escaping_loop.txt index 4513d833f..dda2d46d2 100644 --- a/tests/functional/c/cellvar_escaping_loop.txt +++ b/tests/functional/c/cellvar_escaping_loop.txt @@ -1,13 +1,13 @@ -cell-var-from-loop:101:27:bad_case.<lambda>:Cell variable i defined in loop:HIGH -cell-var-from-loop:106:20:bad_case2.<lambda>:Cell variable i defined in loop:HIGH -cell-var-from-loop:114:27:bad_case3.<lambda>:Cell variable j defined in loop:HIGH -cell-var-from-loop:124:19:bad_case4.nested:Cell variable i defined in loop:HIGH -cell-var-from-loop:145:20:bad_case5.<lambda>:Cell variable i defined in loop:HIGH -cell-var-from-loop:153:27:bad_case6.<lambda>:Cell variable i defined in loop:HIGH -cell-var-from-loop:161:12:bad_case7.<lambda>:Cell variable x defined in loop:HIGH -cell-var-from-loop:162:14:bad_case7.<lambda>:Cell variable y defined in loop:HIGH -cell-var-from-loop:171:27:bad_case8.<lambda>:Cell variable j defined in loop:HIGH -cell-var-from-loop:181:27:bad_case9.<lambda>:Cell variable i defined in loop:HIGH -cell-var-from-loop:190:26:bad_case10.func.func2:Cell variable i defined in loop:HIGH -cell-var-from-loop:202:17:bad_case_issue2846.<lambda>:Cell variable n defined in loop:HIGH -cell-var-from-loop:207:18:bad_case_issue2846.<lambda>:Cell variable n defined in loop:HIGH +cell-var-from-loop:117:27:bad_case.<lambda>:Cell variable i defined in loop:HIGH +cell-var-from-loop:122:20:bad_case2.<lambda>:Cell variable i defined in loop:HIGH +cell-var-from-loop:130:27:bad_case3.<lambda>:Cell variable j defined in loop:HIGH +cell-var-from-loop:140:19:bad_case4.nested:Cell variable i defined in loop:HIGH +cell-var-from-loop:161:20:bad_case5.<lambda>:Cell variable i defined in loop:HIGH +cell-var-from-loop:169:27:bad_case6.<lambda>:Cell variable i defined in loop:HIGH +cell-var-from-loop:177:12:bad_case7.<lambda>:Cell variable x defined in loop:HIGH +cell-var-from-loop:178:14:bad_case7.<lambda>:Cell variable y defined in loop:HIGH +cell-var-from-loop:187:27:bad_case8.<lambda>:Cell variable j defined in loop:HIGH +cell-var-from-loop:197:27:bad_case9.<lambda>:Cell variable i defined in loop:HIGH +cell-var-from-loop:206:26:bad_case10.func.func2:Cell variable i defined in loop:HIGH +cell-var-from-loop:218:17:bad_case_issue2846.<lambda>:Cell variable n defined in loop:HIGH +cell-var-from-loop:223:18:bad_case_issue2846.<lambda>:Cell variable n defined in loop:HIGH |