Skip to content

Commit e907020

Browse files
Fix use-sequence-for-iteration when unpacking a set with * (#7975) (#7988)
Co-authored-by: Dani Alcala <[email protected]>
1 parent c3d7b39 commit e907020

File tree

7 files changed

+46
-11
lines changed

7 files changed

+46
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``use-sequence-for-iteration`` when unpacking a set with ``*``.
2+
3+
Closes #5788

pylint/checkers/refactoring/recommendation_checker.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from pylint import checkers
1111
from pylint.checkers import utils
12+
from pylint.interfaces import HIGH
1213

1314

1415
class RecommendationChecker(checkers.BaseChecker):
@@ -326,9 +327,16 @@ def _check_consider_using_dict_items_comprehension(
326327
def _check_use_sequence_for_iteration(
327328
self, node: nodes.For | nodes.Comprehension
328329
) -> None:
329-
"""Check if code iterates over an in-place defined set."""
330-
if isinstance(node.iter, nodes.Set):
331-
self.add_message("use-sequence-for-iteration", node=node.iter)
330+
"""Check if code iterates over an in-place defined set.
331+
332+
Sets using `*` are not considered in-place.
333+
"""
334+
if isinstance(node.iter, nodes.Set) and not any(
335+
utils.has_starred_node_recursive(node)
336+
):
337+
self.add_message(
338+
"use-sequence-for-iteration", node=node.iter, confidence=HIGH
339+
)
332340

333341
@utils.only_required_for_messages("consider-using-f-string")
334342
def visit_const(self, node: nodes.Const) -> None:

pylint/checkers/utils.py

+14
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,20 @@ def find_assigned_names_recursive(
19611961
yield from find_assigned_names_recursive(elt)
19621962

19631963

1964+
def has_starred_node_recursive(
1965+
node: nodes.For | nodes.Comprehension | nodes.Set,
1966+
) -> Iterator[bool]:
1967+
"""Yield ``True`` if a Starred node is found recursively."""
1968+
if isinstance(node, nodes.Starred):
1969+
yield True
1970+
elif isinstance(node, nodes.Set):
1971+
for elt in node.elts:
1972+
yield from has_starred_node_recursive(elt)
1973+
elif isinstance(node, (nodes.For, nodes.Comprehension)):
1974+
for elt in node.iter.elts:
1975+
yield from has_starred_node_recursive(elt)
1976+
1977+
19641978
def is_hashable(node: nodes.NodeNG) -> bool:
19651979
"""Return whether any inferred value of `node` is hashable.
19661980

tests/functional/ext/code_style/cs_consider_using_tuple.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828

2929
# Don't emit warning for sets as this is handled by builtin checker
3030
(x for x in {1, 2, 3}) # [use-sequence-for-iteration]
31-
[x for x in {*var, 2}] # [use-sequence-for-iteration]
31+
[x for x in {*var, 2}]

tests/functional/ext/code_style/cs_consider_using_tuple.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ consider-using-tuple:18:12:18:21::Consider using an in-place tuple instead of li
44
consider-using-tuple:21:9:21:15::Consider using an in-place tuple instead of list:UNDEFINED
55
consider-using-tuple:23:9:23:18::Consider using an in-place tuple instead of list:UNDEFINED
66
consider-using-tuple:26:12:26:21::Consider using an in-place tuple instead of list:UNDEFINED
7-
use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:UNDEFINED
8-
use-sequence-for-iteration:31:12:31:21::Use a sequence type when iterating over values:UNDEFINED
7+
use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:HIGH

tests/functional/u/use/use_sequence_for_iteration.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,16 @@
1313
[x for x in var]
1414
[x for x in {1, 2, 3}] # [use-sequence-for-iteration]
1515

16-
[x for x in {*var, 4}] # [use-sequence-for-iteration]
16+
[x for x in {*var, 4}]
17+
18+
def deduplicate(list_in):
19+
for thing in {*list_in}:
20+
print(thing)
21+
22+
def deduplicate_two_lists(input1, input2):
23+
for thing in {*input1, *input2}:
24+
print(thing)
25+
26+
def deduplicate_nested_sets(input1, input2, input3, input4):
27+
for thing in {{*input1, *input2}, {*input3, *input4}}:
28+
print(thing)
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:UNDEFINED
2-
use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:UNDEFINED
3-
use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:UNDEFINED
4-
use-sequence-for-iteration:16:12:16:21::Use a sequence type when iterating over values:UNDEFINED
1+
use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:HIGH
2+
use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:HIGH
3+
use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:HIGH

0 commit comments

Comments
 (0)