diff options
Diffstat (limited to 'pylint/checkers/refactoring/refactoring_checker.py')
-rw-r--r-- | pylint/checkers/refactoring/refactoring_checker.py | 88 |
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): |