diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2022-12-26 13:16:46 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-26 19:16:46 +0100 |
commit | e90702074e68e20dc8e5df5013ee3ecf22139c3e (patch) | |
tree | 69d06e887e05fb4501dac470e34dc7581d977289 | |
parent | c3d7b3963b5e36939debcc5d608567fab429724c (diff) | |
download | pylint-git-e90702074e68e20dc8e5df5013ee3ecf22139c3e.tar.gz |
Fix `use-sequence-for-iteration` when unpacking a set with `*` (#7975) (#7988)
Co-authored-by: Dani Alcala <112832187+clavedeluna@users.noreply.github.com>
-rw-r--r-- | doc/whatsnew/fragments/5788.false_positive | 3 | ||||
-rw-r--r-- | pylint/checkers/refactoring/recommendation_checker.py | 14 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 14 | ||||
-rw-r--r-- | tests/functional/ext/code_style/cs_consider_using_tuple.py | 2 | ||||
-rw-r--r-- | tests/functional/ext/code_style/cs_consider_using_tuple.txt | 3 | ||||
-rw-r--r-- | tests/functional/u/use/use_sequence_for_iteration.py | 14 | ||||
-rw-r--r-- | tests/functional/u/use/use_sequence_for_iteration.txt | 7 |
7 files changed, 46 insertions, 11 deletions
diff --git a/doc/whatsnew/fragments/5788.false_positive b/doc/whatsnew/fragments/5788.false_positive new file mode 100644 index 000000000..65fc29fe4 --- /dev/null +++ b/doc/whatsnew/fragments/5788.false_positive @@ -0,0 +1,3 @@ +Fix ``use-sequence-for-iteration`` when unpacking a set with ``*``. + +Closes #5788 diff --git a/pylint/checkers/refactoring/recommendation_checker.py b/pylint/checkers/refactoring/recommendation_checker.py index 7873dc25e..e1634fd8c 100644 --- a/pylint/checkers/refactoring/recommendation_checker.py +++ b/pylint/checkers/refactoring/recommendation_checker.py @@ -9,6 +9,7 @@ from astroid import nodes from pylint import checkers from pylint.checkers import utils +from pylint.interfaces import HIGH class RecommendationChecker(checkers.BaseChecker): @@ -326,9 +327,16 @@ class RecommendationChecker(checkers.BaseChecker): def _check_use_sequence_for_iteration( self, node: nodes.For | nodes.Comprehension ) -> None: - """Check if code iterates over an in-place defined set.""" - if isinstance(node.iter, nodes.Set): - self.add_message("use-sequence-for-iteration", node=node.iter) + """Check if code iterates over an in-place defined set. + + Sets using `*` are not considered in-place. + """ + if isinstance(node.iter, nodes.Set) and not any( + utils.has_starred_node_recursive(node) + ): + self.add_message( + "use-sequence-for-iteration", node=node.iter, confidence=HIGH + ) @utils.only_required_for_messages("consider-using-f-string") def visit_const(self, node: nodes.Const) -> None: diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 90339ad50..da7667f46 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -1961,6 +1961,20 @@ def find_assigned_names_recursive( yield from find_assigned_names_recursive(elt) +def has_starred_node_recursive( + node: nodes.For | nodes.Comprehension | nodes.Set, +) -> Iterator[bool]: + """Yield ``True`` if a Starred node is found recursively.""" + if isinstance(node, nodes.Starred): + yield True + elif isinstance(node, nodes.Set): + for elt in node.elts: + yield from has_starred_node_recursive(elt) + elif isinstance(node, (nodes.For, nodes.Comprehension)): + for elt in node.iter.elts: + yield from has_starred_node_recursive(elt) + + def is_hashable(node: nodes.NodeNG) -> bool: """Return whether any inferred value of `node` is hashable. diff --git a/tests/functional/ext/code_style/cs_consider_using_tuple.py b/tests/functional/ext/code_style/cs_consider_using_tuple.py index d24396079..57178c34e 100644 --- a/tests/functional/ext/code_style/cs_consider_using_tuple.py +++ b/tests/functional/ext/code_style/cs_consider_using_tuple.py @@ -28,4 +28,4 @@ for x in [2, *var]: # [consider-using-tuple] # Don't emit warning for sets as this is handled by builtin checker (x for x in {1, 2, 3}) # [use-sequence-for-iteration] -[x for x in {*var, 2}] # [use-sequence-for-iteration] +[x for x in {*var, 2}] diff --git a/tests/functional/ext/code_style/cs_consider_using_tuple.txt b/tests/functional/ext/code_style/cs_consider_using_tuple.txt index cd8ffb1e7..565f5f778 100644 --- a/tests/functional/ext/code_style/cs_consider_using_tuple.txt +++ b/tests/functional/ext/code_style/cs_consider_using_tuple.txt @@ -4,5 +4,4 @@ consider-using-tuple:18:12:18:21::Consider using an in-place tuple instead of li consider-using-tuple:21:9:21:15::Consider using an in-place tuple instead of list:UNDEFINED consider-using-tuple:23:9:23:18::Consider using an in-place tuple instead of list:UNDEFINED consider-using-tuple:26:12:26:21::Consider using an in-place tuple instead of list:UNDEFINED -use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:31:12:31:21::Use a sequence type when iterating over values:UNDEFINED +use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:HIGH diff --git a/tests/functional/u/use/use_sequence_for_iteration.py b/tests/functional/u/use/use_sequence_for_iteration.py index 2dd1feb18..264e6e7b9 100644 --- a/tests/functional/u/use/use_sequence_for_iteration.py +++ b/tests/functional/u/use/use_sequence_for_iteration.py @@ -13,4 +13,16 @@ for x in {1, 2, 3}: # [use-sequence-for-iteration] [x for x in var] [x for x in {1, 2, 3}] # [use-sequence-for-iteration] -[x for x in {*var, 4}] # [use-sequence-for-iteration] +[x for x in {*var, 4}] + +def deduplicate(list_in): + for thing in {*list_in}: + print(thing) + +def deduplicate_two_lists(input1, input2): + for thing in {*input1, *input2}: + print(thing) + +def deduplicate_nested_sets(input1, input2, input3, input4): + for thing in {{*input1, *input2}, {*input3, *input4}}: + print(thing) diff --git a/tests/functional/u/use/use_sequence_for_iteration.txt b/tests/functional/u/use/use_sequence_for_iteration.txt index beb23a4df..3787b7a0e 100644 --- a/tests/functional/u/use/use_sequence_for_iteration.txt +++ b/tests/functional/u/use/use_sequence_for_iteration.txt @@ -1,4 +1,3 @@ -use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:16:12:16:21::Use a sequence type when iterating over values:UNDEFINED +use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:HIGH |