summaryrefslogtreecommitdiff
path: root/pylint/checkers/refactoring/refactoring_checker.py
diff options
context:
space:
mode:
Diffstat (limited to 'pylint/checkers/refactoring/refactoring_checker.py')
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py88
1 files changed, 88 insertions, 0 deletions
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index a95bed97b..bab86b4bf 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -291,6 +291,16 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"Comprehension inside of 'any' or 'all' is unnecessary. "
"A generator would be sufficient and faster.",
),
+ "R1730": (
+ "Consider using '%s' instead of unnecessary if block",
+ "consider-using-min-builtin",
+ "Using the min builtin instead of a conditional improves readability and conciseness.",
+ ),
+ "R1731": (
+ "Consider using '%s' instead of unnecessary if block",
+ "consider-using-max-builtin",
+ "Using the max builtin instead of a conditional improves readability and conciseness.",
+ ),
}
options = (
(
@@ -609,6 +619,84 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self._check_superfluous_else_break(node)
self._check_superfluous_else_continue(node)
self._check_consider_get(node)
+ self._check_consider_using_min_max_builtin(node)
+
+ def _check_consider_using_min_max_builtin(self, node: astroid.If):
+ """Check if the given if node can be refactored as an min/max python builtin."""
+ if self._is_actual_elif(node) or node.orelse:
+ # Not interested in if statements with multiple branches.
+ return
+
+ if len(node.body) != 1:
+ return
+
+ body = node.body[0]
+ # Check if condition can be reduced.
+ if not hasattr(body, "targets") or len(body.targets) != 1:
+ return
+
+ target = body.targets[0]
+ if not (
+ isinstance(node.test, astroid.Compare)
+ and not isinstance(target, astroid.Subscript)
+ and not isinstance(node.test.left, astroid.Subscript)
+ and isinstance(body, astroid.Assign)
+ ):
+ return
+
+ # Check that the assignation is on the same variable.
+ if hasattr(node.test.left, "name"):
+ left_operand = node.test.left.name
+ elif hasattr(node.test.left, "attrname"):
+ left_operand = node.test.left.attrname
+ else:
+ return
+
+ if hasattr(target, "name"):
+ target_assignation = target.name
+ elif hasattr(target, "attrname"):
+ target_assignation = target.attrname
+ else:
+ return
+
+ if not (left_operand == target_assignation):
+ return
+
+ if len(node.test.ops) > 1:
+ return
+
+ if not isinstance(body.value, (astroid.Name, astroid.Const)):
+ return
+
+ operator, right_statement = node.test.ops[0]
+ if isinstance(body.value, astroid.Name):
+ body_value = body.value.name
+ else:
+ body_value = body.value.value
+
+ if isinstance(right_statement, astroid.Name):
+ right_statement_value = right_statement.name
+ else:
+ right_statement_value = right_statement.value
+
+ # Verify the right part of the statement is the same.
+ if right_statement_value != body_value:
+ return
+
+ if operator in ("<", "<="):
+ reduced_to = "{target} = max({target}, {item})".format(
+ target=target_assignation, item=body_value
+ )
+ self.add_message(
+ "consider-using-max-builtin", node=node, args=(reduced_to,)
+ )
+ elif operator in (">", ">="):
+ reduced_to = "{target} = min({target}, {item})".format(
+ target=target_assignation, item=body_value
+ )
+ self.add_message(
+ "consider-using-min-builtin", node=node, args=(reduced_to,)
+ )
@utils.check_messages("simplifiable-if-expression")
def visit_ifexp(self, node):