14
14
15
15
from pylint .checkers import BaseChecker
16
16
from pylint .checkers .utils import only_required_for_messages , safe_infer
17
+ from pylint .constants import PY39_PLUS
17
18
from pylint .interfaces import INFERENCE
18
19
19
20
if TYPE_CHECKING :
@@ -93,13 +94,10 @@ def visit_call(self, node: nodes.Call) -> None:
93
94
94
95
for idx , arg in enumerate (fixed_node .args ):
95
96
if not isinstance (arg , nodes .Const ):
96
- inferred = safe_infer (arg )
97
- if isinstance (
98
- inferred , (nodes .List , nodes .Tuple , nodes .Set , * DICT_TYPES )
99
- ):
97
+ if self ._is_splattable_expression (arg ):
100
98
splat_node = nodes .Starred (
101
99
ctx = Context .Load ,
102
- lineno = inferred .lineno ,
100
+ lineno = arg .lineno ,
103
101
col_offset = 0 ,
104
102
parent = nodes .NodeNG (
105
103
lineno = None ,
@@ -125,6 +123,39 @@ def visit_call(self, node: nodes.Call) -> None:
125
123
confidence = INFERENCE ,
126
124
)
127
125
126
+ def _is_splattable_expression (self , arg : nodes .NodeNG ) -> bool :
127
+ """Returns true if expression under min/max could be converted to splat
128
+ expression.
129
+ """
130
+ # Support sequence addition (operator __add__)
131
+ if isinstance (arg , nodes .BinOp ) and arg .op == "+" :
132
+ return self ._is_splattable_expression (
133
+ arg .left
134
+ ) and self ._is_splattable_expression (arg .right )
135
+ # Support dict merge (operator __or__ in Python 3.9)
136
+ if isinstance (arg , nodes .BinOp ) and arg .op == "|" and PY39_PLUS :
137
+ return self ._is_splattable_expression (
138
+ arg .left
139
+ ) and self ._is_splattable_expression (arg .right )
140
+
141
+ inferred = safe_infer (arg )
142
+ if inferred and inferred .pytype () in {"builtins.list" , "builtins.tuple" }:
143
+ return True
144
+ if isinstance (
145
+ inferred or arg ,
146
+ (
147
+ nodes .List ,
148
+ nodes .Tuple ,
149
+ nodes .Set ,
150
+ nodes .ListComp ,
151
+ nodes .DictComp ,
152
+ * DICT_TYPES ,
153
+ ),
154
+ ):
155
+ return True
156
+
157
+ return False
158
+
128
159
129
160
def register (linter : PyLinter ) -> None :
130
161
linter .register_checker (NestedMinMaxChecker (linter ))
0 commit comments