summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2022-12-26 13:16:46 -0500
committerGitHub <noreply@github.com>2022-12-26 19:16:46 +0100
commite90702074e68e20dc8e5df5013ee3ecf22139c3e (patch)
tree69d06e887e05fb4501dac470e34dc7581d977289
parentc3d7b3963b5e36939debcc5d608567fab429724c (diff)
downloadpylint-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_positive3
-rw-r--r--pylint/checkers/refactoring/recommendation_checker.py14
-rw-r--r--pylint/checkers/utils.py14
-rw-r--r--tests/functional/ext/code_style/cs_consider_using_tuple.py2
-rw-r--r--tests/functional/ext/code_style/cs_consider_using_tuple.txt3
-rw-r--r--tests/functional/u/use/use_sequence_for_iteration.py14
-rw-r--r--tests/functional/u/use/use_sequence_for_iteration.txt7
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