mirror of https://github.com/astral-sh/ruff
Complete `flake8-simplify` documentation (#4930)
This commit is contained in:
parent
293889a352
commit
efd8f3bdab
|
|
@ -70,6 +70,28 @@ impl Violation for DuplicateIsinstanceCall {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for boolean expressions that contain multiple equality comparisons
|
||||
/// to the same value.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// To check if an object is equal to any one of multiple values, it's more
|
||||
/// concise to use the `in` operator with a tuple of values.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if foo == x or foo == y:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// if foo in (x, y):
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Membership test operations](https://docs.python.org/3/reference/expressions.html#membership-test-operations)
|
||||
#[violation]
|
||||
pub struct CompareWithTuple {
|
||||
replacement: String,
|
||||
|
|
@ -88,6 +110,21 @@ impl AlwaysAutofixableViolation for CompareWithTuple {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `and` expressions that include both an expression and its
|
||||
/// negation.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// An `and` expression that includes both an expression and its negation will
|
||||
/// always evaluate to `False`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// x and not x
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Boolean operations](https://docs.python.org/3/reference/expressions.html#boolean-operations)
|
||||
#[violation]
|
||||
pub struct ExprAndNotExpr {
|
||||
name: String,
|
||||
|
|
@ -105,6 +142,21 @@ impl AlwaysAutofixableViolation for ExprAndNotExpr {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `or` expressions that include both an expression and its
|
||||
/// negation.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// An `or` expression that includes both an expression and its negation will
|
||||
/// always evaluate to `True`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// x and not x
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Boolean operations](https://docs.python.org/3/reference/expressions.html#boolean-operations)
|
||||
#[violation]
|
||||
pub struct ExprOrNotExpr {
|
||||
name: String,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,31 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Check for environment variables that are not capitalized.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// By convention, environment variables should be capitalized.
|
||||
///
|
||||
/// On Windows, environment variables are case-insensitive and are converted to
|
||||
/// uppercase, so using lowercase environment variables can lead to subtle bugs.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.environ["foo"]
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.environ["FOO"]
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `os.environ`](https://docs.python.org/3/library/os.html#os.environ)
|
||||
#[violation]
|
||||
pub struct UncapitalizedEnvironmentVariables {
|
||||
expected: String,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,31 @@ fn compare_body(body1: &[Stmt], body2: &[Stmt]) -> bool {
|
|||
.all(|(stmt1, stmt2)| compare_stmt(&stmt1.into(), &stmt2.into()))
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for nested `if` statements that can be collapsed into a single `if`
|
||||
/// statement.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Nesting `if` statements leads to deeper indentation and makes code harder to
|
||||
/// read. Instead, combine the conditions into a single `if` statement with an
|
||||
/// `and` operator.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if foo:
|
||||
/// if bar:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// if foo and bar:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: The `if` statement](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement)
|
||||
/// - [Python documentation: Boolean operations](https://docs.python.org/3/reference/expressions.html#boolean-operations)
|
||||
#[violation]
|
||||
pub struct CollapsibleIf;
|
||||
|
||||
|
|
@ -51,6 +76,28 @@ impl Violation for CollapsibleIf {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` statements that can be replaced with `bool`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `if` statements that return `True` for a truthy condition and `False` for
|
||||
/// a falsey condition can be replaced with boolean casts.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if foo:
|
||||
/// return True
|
||||
/// else:
|
||||
/// return False
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// return bool(foo)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Truth Value Testing](https://docs.python.org/3/library/stdtypes.html#truth-value-testing)
|
||||
#[violation]
|
||||
pub struct NeedlessBool {
|
||||
condition: String,
|
||||
|
|
@ -101,6 +148,28 @@ impl Violation for IfElseBlockInsteadOfDictLookup {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Check for `if`-`else`-blocks that can be replaced with a ternary operator.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `if`-`else`-blocks that assign a value to a variable in both branches can
|
||||
/// be expressed more concisely by using a ternary operator.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if foo:
|
||||
/// bar = x
|
||||
/// else:
|
||||
/// bar = y
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// bar = x if foo else y
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Conditional expressions](https://docs.python.org/3/reference/expressions.html#conditional-expressions)
|
||||
#[violation]
|
||||
pub struct IfElseBlockInsteadOfIfExp {
|
||||
contents: String,
|
||||
|
|
@ -151,6 +220,30 @@ impl Violation for IfWithSameArms {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` statements that can be replaced with `dict.get` calls.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `dict.get()` calls can be used to replace `if` statements that assign a
|
||||
/// value to a variable in both branches, falling back to a default value if
|
||||
/// the key is not found. When possible, using `dict.get` is more concise and
|
||||
/// more idiomatic.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if "bar" in foo:
|
||||
/// value = foo["bar"]
|
||||
/// else:
|
||||
/// value = 0
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// value = foo.get("bar", 0)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Mapping Types](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict)
|
||||
#[violation]
|
||||
pub struct IfElseBlockInsteadOfDictGet {
|
||||
contents: String,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,26 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` expressions that can be replaced with `bool()` calls.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `if` expressions that evaluate to `True` for a truthy condition an `False`
|
||||
/// for a falsey condition can be replaced with `bool()` calls, which are more
|
||||
/// concise and readable.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// True if a else False
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// bool(a)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Truth Value Testing](https://docs.python.org/3/library/stdtypes.html#truth-value-testing)
|
||||
#[violation]
|
||||
pub struct IfExprWithTrueFalse {
|
||||
expr: String,
|
||||
|
|
@ -27,6 +47,27 @@ impl Violation for IfExprWithTrueFalse {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` expressions that can be replaced by negating a given
|
||||
/// condition.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `if` expressions that evaluate to `False` for a truthy condition an `True`
|
||||
/// for a falsey condition can be replaced with `not` operators, which are more
|
||||
/// concise and readable.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// False if a else True
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// not a
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Truth Value Testing](https://docs.python.org/3/library/stdtypes.html#truth-value-testing)
|
||||
#[violation]
|
||||
pub struct IfExprWithFalseTrue {
|
||||
expr: String,
|
||||
|
|
@ -45,6 +86,25 @@ impl AlwaysAutofixableViolation for IfExprWithFalseTrue {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` expressions that check against a negated condition.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `if` expressions that check against a negated condition are more difficult
|
||||
/// to read than `if` expressions that check against the condition directly.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// b if not a else a
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a if a else b
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Truth Value Testing](https://docs.python.org/3/library/stdtypes.html#truth-value-testing)
|
||||
#[violation]
|
||||
pub struct IfExprWithTwistedArms {
|
||||
expr_body: String,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,25 @@ use ruff_python_semantic::scope::ScopeKind;
|
|||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for negated `==` operators.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Negated `==` operators are less readable than `!=` operators. When testing
|
||||
/// for non-equality, it is more common to use `!=` than `==`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// not a == b
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a != b
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Comparisons](https://docs.python.org/3/reference/expressions.html#comparisons)
|
||||
#[violation]
|
||||
pub struct NegateEqualOp {
|
||||
left: String,
|
||||
|
|
@ -26,6 +45,25 @@ impl AlwaysAutofixableViolation for NegateEqualOp {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for negated `!=` operators.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Negated `!=` operators are less readable than `==` operators, as they avoid a
|
||||
/// double negation.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// not a != b
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a == b
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Comparisons](https://docs.python.org/3/reference/expressions.html#comparisons)
|
||||
#[violation]
|
||||
pub struct NegateNotEqualOp {
|
||||
left: String,
|
||||
|
|
@ -44,6 +82,25 @@ impl AlwaysAutofixableViolation for NegateNotEqualOp {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for double negations (i.e., multiple `not` operators).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// A double negation is redundant and less readable than omitting the `not`
|
||||
/// operators entirely.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// not (not a)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Comparisons](https://docs.python.org/3/reference/expressions.html#comparisons)
|
||||
#[violation]
|
||||
pub struct DoubleNegation {
|
||||
expr: String,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,26 @@ use crate::checkers::ast::Checker;
|
|||
use crate::cst::matchers::{match_attribute, match_call_mut, match_expression};
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for key-existence checks against `dict.keys()` calls.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// When checking for the existence of a key in a given dictionary, using
|
||||
/// `key in dict` is more readable and efficient than `key in dict.keys()`,
|
||||
/// while having the same semantics.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// key in foo.keys()
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// key in foo
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Mapping Types](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict)
|
||||
#[violation]
|
||||
pub struct InDictKeys {
|
||||
key: String,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,30 @@ use crate::checkers::ast::Checker;
|
|||
use crate::line_width::LineWidth;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `for` loops that can be replaced with a builtin function, like
|
||||
/// `any` or `all`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Using a builtin function is more concise and readable. Builtins are also
|
||||
/// more efficient than `for` loops.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// for item in iterable:
|
||||
/// if predicate(item):
|
||||
/// return True
|
||||
/// return False
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// return any(predicate(item) for item in iterable)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `any`](https://docs.python.org/3/library/functions.html#any)
|
||||
/// - [Python documentation: `all`](https://docs.python.org/3/library/functions.html#all)
|
||||
#[violation]
|
||||
pub struct ReimplementedBuiltin {
|
||||
repl: String,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,38 @@ use crate::checkers::ast::Checker;
|
|||
use crate::importer::ImportRequest;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `try`-`except`-`pass` blocks that can be replaced with the
|
||||
/// `contextlib.suppress` context manager.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Using `contextlib.suppress` is more concise and directly communicates the
|
||||
/// intent of the code: to suppress a given exception.
|
||||
///
|
||||
/// Note that `contextlib.suppress` is slower than using `try`-`except`-`pass`
|
||||
/// directly. For performance-critical code, consider retaining the
|
||||
/// `try`-`except`-`pass` pattern.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// try:
|
||||
/// 1 / 0
|
||||
/// except ZeroDivisionError:
|
||||
/// pass
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// import contextlib
|
||||
///
|
||||
/// with contextlib.suppress(ZeroDivisionError):
|
||||
/// 1 / 0
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `contextlib.suppress`](https://docs.python.org/3/library/contextlib.html#contextlib.suppress)
|
||||
/// - [Python documentation: `try` statement](https://docs.python.org/3/reference/compound_stmts.html#the-try-statement)
|
||||
/// - [a simpler `try`/`except` (and why maybe shouldn't)](https://www.youtube.com/watch?v=MZAJ8qnC7mk)
|
||||
#[violation]
|
||||
pub struct SuppressibleException {
|
||||
exception: String,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,36 @@ use crate::checkers::ast::Checker;
|
|||
use crate::cst::matchers::{match_comparison, match_expression};
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for conditions that position a constant on the left-hand side of the
|
||||
/// comparison operator, rather than the right-hand side.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// These conditions (sometimes referred to as "Yoda conditions") are less
|
||||
/// readable than conditions that place the variable on the left-hand side of
|
||||
/// the comparison operator.
|
||||
///
|
||||
/// In some languages, Yoda conditions are used to prevent accidental
|
||||
/// assignment in conditions (i.e., accidental uses of the `=` operator,
|
||||
/// instead of the `==` operator). However, Python does not allow assignments
|
||||
/// in conditions unless using the `:=` operator, so Yoda conditions provide
|
||||
/// no benefit in this regard.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if "Foo" == foo:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// if foo == "Foo":
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Comparisons](https://docs.python.org/3/reference/expressions.html#comparisons)
|
||||
/// - [Python documentation: Assignment statements](https://docs.python.org/3/reference/simple_stmts.html#assignment-statements)
|
||||
#[violation]
|
||||
pub struct YodaConditions {
|
||||
pub suggestion: Option<String>,
|
||||
|
|
|
|||
Loading…
Reference in New Issue