Clearly indicate what is counted as a branch (#11423)
## Summary As discussed in issue #11408, PLR0912 has a broader definition of "branches" than I expected. This updates the documentation to include this definition. I also updated the example to include several different types of branches, while still maintaining dictionary lookup as an alternative solution. (Crafting a realistic example was quite a challenge 😅). Closes https://github.com/astral-sh/ruff/issues/11408.
This commit is contained in:
@@ -5,7 +5,9 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::identifier::Identifier;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for functions or methods with too many branches.
|
||||
/// Checks for functions or methods with too many branches, including (nested)
|
||||
/// `if`, `elif`, and `else` branches, `for` loops, `try`-`except` clauses, and
|
||||
/// `match` and `case` statements.
|
||||
///
|
||||
/// By default, this rule allows up to 12 branches. This can be configured
|
||||
/// using the [`lint.pylint.max-branches`] option.
|
||||
@@ -15,6 +17,7 @@ use ruff_python_ast::identifier::Identifier;
|
||||
/// and maintain than functions or methods with fewer branches.
|
||||
///
|
||||
/// ## Example
|
||||
/// Given:
|
||||
/// ```python
|
||||
/// def capital(country):
|
||||
/// if country == "Australia":
|
||||
@@ -66,6 +69,77 @@ use ruff_python_ast::identifier::Identifier;
|
||||
/// return city
|
||||
/// ```
|
||||
///
|
||||
/// Given:
|
||||
/// ```python
|
||||
/// def grades_to_average_number(grades):
|
||||
/// numbers = []
|
||||
/// for grade in grades: # 1st branch
|
||||
/// if len(grade) not in {1, 2}:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
///
|
||||
/// if len(grade) == 2 and grade[1] not in {"+", "-"}:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
///
|
||||
/// letter = grade[0]
|
||||
///
|
||||
/// if letter in {"F", "E"}:
|
||||
/// number = 0.0
|
||||
/// elif letter == "D":
|
||||
/// number = 1.0
|
||||
/// elif letter == "C":
|
||||
/// number = 2.0
|
||||
/// elif letter == "B":
|
||||
/// number = 3.0
|
||||
/// elif letter == "A":
|
||||
/// number = 4.0
|
||||
/// else:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
///
|
||||
/// modifier = 0.0
|
||||
/// if letter != "F" and grade[-1] == "+":
|
||||
/// modifier = 0.3
|
||||
/// elif letter != "F" and grade[-1] == "-":
|
||||
/// modifier = -0.3
|
||||
///
|
||||
/// numbers.append(max(0.0, min(number + modifier, 4.0)))
|
||||
///
|
||||
/// try:
|
||||
/// return sum(numbers) / len(numbers)
|
||||
/// except ZeroDivisionError: # 13th branch
|
||||
/// return 0
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def grades_to_average_number(grades):
|
||||
/// grade_values = {"F": 0.0, "E": 0.0, "D": 1.0, "C": 2.0, "B": 3.0, "A": 4.0}
|
||||
/// modifier_values = {"+": 0.3, "-": -0.3}
|
||||
///
|
||||
/// numbers = []
|
||||
/// for grade in grades:
|
||||
/// if len(grade) not in {1, 2}:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
///
|
||||
/// letter = grade[0]
|
||||
/// if letter not in grade_values:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
/// number = grade_values[letter]
|
||||
///
|
||||
/// if len(grade) == 2 and grade[1] not in modifier_values:
|
||||
/// raise ValueError(f"Invalid grade: {grade}")
|
||||
/// modifier = modifier_values.get(grade[-1], 0.0)
|
||||
///
|
||||
/// if letter == "F":
|
||||
/// numbers.append(0.0)
|
||||
/// else:
|
||||
/// numbers.append(max(0.0, min(number + modifier, 4.0)))
|
||||
///
|
||||
/// try:
|
||||
/// return sum(numbers) / len(numbers)
|
||||
/// except ZeroDivisionError:
|
||||
/// return 0
|
||||
/// ```
|
||||
///
|
||||
/// ## Options
|
||||
/// - `lint.pylint.max-branches`
|
||||
#[violation]
|
||||
|
||||
Reference in New Issue
Block a user