Skip to content

Commit

Permalink
Fix nested-min-max output msg for sequences (#8234)
Browse files Browse the repository at this point in the history
  • Loading branch information
clavedeluna authored Feb 8, 2023
1 parent 7fd499a commit 29684fe
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doc/whatsnew/fragments/8168.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix ``nested-min-max`` suggestion message to indicate it's possible to splat iterable objects.

Closes #8168
23 changes: 22 additions & 1 deletion pylint/checkers/nested_min_max.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import copy
from typing import TYPE_CHECKING

from astroid import nodes
from astroid import nodes, objects

from pylint.checkers import BaseChecker
from pylint.checkers.utils import only_required_for_messages, safe_infer
Expand All @@ -18,6 +18,13 @@
if TYPE_CHECKING:
from pylint.lint import PyLinter

DICT_TYPES = (
objects.DictValues,
objects.DictKeys,
objects.DictItems,
nodes.node_classes.Dict,
)


class NestedMinMaxChecker(BaseChecker):
"""Multiple nested min/max calls on the same line will raise multiple messages.
Expand Down Expand Up @@ -83,6 +90,20 @@ def visit_call(self, node: nodes.Call) -> None:

redundant_calls = self.get_redundant_calls(fixed_node)

for idx, arg in enumerate(fixed_node.args):
if not isinstance(arg, nodes.Const):
inferred = safe_infer(arg)
if isinstance(
inferred, (nodes.List, nodes.Tuple, nodes.Set, *DICT_TYPES)
):
splat_node = nodes.Starred(lineno=inferred.lineno)
splat_node.value = arg
fixed_node.args = (
fixed_node.args[:idx]
+ [splat_node]
+ fixed_node.args[idx + 1 : idx]
)

self.add_message(
"nested-min-max",
node=node,
Expand Down
23 changes: 23 additions & 0 deletions tests/functional/n/nested_min_max.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,26 @@
# This is too complicated (for now) as there is no clear better way to write it
max(max(i for i in range(10)), 0)
max(max(max(i for i in range(10)), 0), 1)

# These examples can be improved by splicing
lst = [1, 2]
max(3, max(lst)) # [nested-min-max]
max(3, *lst)

nums = (1, 2,)
max(3, max(nums)) # [nested-min-max]
max(3, *nums)

nums = {1, 2}
max(3, max(nums)) # [nested-min-max]
max(3, *nums)

nums = {1: 2, 7: 10}
max(3, max(nums)) # [nested-min-max]
max(3, *nums)

max(3, max(nums.values())) # [nested-min-max]
max(3, *nums.values())

lst2 = [3, 7, 10]
max(3, max(nums), max(lst2)) # [nested-min-max]
6 changes: 6 additions & 0 deletions tests/functional/n/nested_min_max.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ nested-min-max:8:0:8:25::Do not use nested call of 'min'; it's possible to do 'm
nested-min-max:11:0:11:25::Do not use nested call of 'min'; it's possible to do 'min(1, 2, 3, 4)' instead:INFERENCE
nested-min-max:12:0:12:40::Do not use nested call of 'min'; it's possible to do 'min(len([]), len([1]), len([1, 2]))' instead:INFERENCE
nested-min-max:17:0:17:27::Do not use nested call of 'orig_min'; it's possible to do 'orig_min(1, 2, 3)' instead:INFERENCE
nested-min-max:25:0:25:16::Do not use nested call of 'max'; it's possible to do 'max(3, *lst)' instead:INFERENCE
nested-min-max:29:0:29:17::Do not use nested call of 'max'; it's possible to do 'max(3, *nums)' instead:INFERENCE
nested-min-max:33:0:33:17::Do not use nested call of 'max'; it's possible to do 'max(3, *nums)' instead:INFERENCE
nested-min-max:37:0:37:17::Do not use nested call of 'max'; it's possible to do 'max(3, *nums)' instead:INFERENCE
nested-min-max:40:0:40:26::Do not use nested call of 'max'; it's possible to do 'max(3, *nums.values())' instead:INFERENCE
nested-min-max:44:0:44:28::Do not use nested call of 'max'; it's possible to do 'max(3, *nums, *lst2)' instead:INFERENCE

0 comments on commit 29684fe

Please sign in to comment.