Deprecate define violation (#3358)

* Add `#[violation]` proc macro as a replacement for `define_violation!`

* Switch all rules to #[violation]
This commit is contained in:
konstin 2023-03-06 11:59:06 +01:00 committed by GitHub
parent 22e6778e17
commit 348a38d261
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
305 changed files with 4680 additions and 4635 deletions

View file

@ -104,7 +104,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention).
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
1. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
1. In that file, define a violation struct. You can grep for `#[violation]` to see examples.
1. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
@ -115,7 +115,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
To define the violation, start by creating a dedicated file for your rule under the appropriate
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
contain a struct defined via `define_violation!`, along with a function that creates the violation
contain a struct defined via `#[violation]`, along with a function that creates the violation
based on any required inputs. (Many of the existing examples live in `crates/ruff/src/violations.rs`,
but we're looking to place new rules in their own files.)

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Location;
use super::detection::comment_contains_code;
@ -9,20 +9,20 @@ use crate::settings::{flags, Settings};
use crate::source_code::Locator;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
/// ## What it does
/// Checks for commented-out Python code.
///
/// ## Why is this bad?
/// Commented-out code is dead code, and is often included inadvertently.
/// It should be removed.
///
/// ## Example
/// ```python
/// # print('foo')
/// ```
pub struct CommentedOutCode;
);
/// ## What it does
/// Checks for commented-out Python code.
///
/// ## Why is this bad?
/// Commented-out code is dead code, and is often included inadvertently.
/// It should be removed.
///
/// ## Example
/// ```python
/// # print('foo')
/// ```
#[violation]
pub struct CommentedOutCode;
impl AlwaysAutofixableViolation for CommentedOutCode {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind, Located};
use crate::ast::types::Range;
@ -7,9 +7,9 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation;
define_violation!(
pub struct SysVersionSlice3Referenced;
);
#[violation]
pub struct SysVersionSlice3Referenced;
impl Violation for SysVersionSlice3Referenced {
#[derive_message_formats]
fn message(&self) -> String {
@ -17,9 +17,9 @@ impl Violation for SysVersionSlice3Referenced {
}
}
define_violation!(
pub struct SysVersion2Referenced;
);
#[violation]
pub struct SysVersion2Referenced;
impl Violation for SysVersion2Referenced {
#[derive_message_formats]
fn message(&self) -> String {
@ -27,9 +27,9 @@ impl Violation for SysVersion2Referenced {
}
}
define_violation!(
pub struct SysVersionCmpStr3;
);
#[violation]
pub struct SysVersionCmpStr3;
impl Violation for SysVersionCmpStr3 {
#[derive_message_formats]
fn message(&self) -> String {
@ -37,9 +37,9 @@ impl Violation for SysVersionCmpStr3 {
}
}
define_violation!(
pub struct SysVersionInfo0Eq3Referenced;
);
#[violation]
pub struct SysVersionInfo0Eq3Referenced;
impl Violation for SysVersionInfo0Eq3Referenced {
#[derive_message_formats]
fn message(&self) -> String {
@ -47,9 +47,9 @@ impl Violation for SysVersionInfo0Eq3Referenced {
}
}
define_violation!(
pub struct SixPY3Referenced;
);
#[violation]
pub struct SixPY3Referenced;
impl Violation for SixPY3Referenced {
#[derive_message_formats]
fn message(&self) -> String {
@ -57,9 +57,9 @@ impl Violation for SixPY3Referenced {
}
}
define_violation!(
pub struct SysVersionInfo1CmpInt;
);
#[violation]
pub struct SysVersionInfo1CmpInt;
impl Violation for SysVersionInfo1CmpInt {
#[derive_message_formats]
fn message(&self) -> String {
@ -70,9 +70,9 @@ impl Violation for SysVersionInfo1CmpInt {
}
}
define_violation!(
pub struct SysVersionInfoMinorCmpInt;
);
#[violation]
pub struct SysVersionInfoMinorCmpInt;
impl Violation for SysVersionInfoMinorCmpInt {
#[derive_message_formats]
fn message(&self) -> String {
@ -83,9 +83,9 @@ impl Violation for SysVersionInfoMinorCmpInt {
}
}
define_violation!(
pub struct SysVersion0Referenced;
);
#[violation]
pub struct SysVersion0Referenced;
impl Violation for SysVersion0Referenced {
#[derive_message_formats]
fn message(&self) -> String {
@ -93,9 +93,9 @@ impl Violation for SysVersion0Referenced {
}
}
define_violation!(
pub struct SysVersionCmpStr10;
);
#[violation]
pub struct SysVersionCmpStr10;
impl Violation for SysVersionCmpStr10 {
#[derive_message_formats]
fn message(&self) -> String {
@ -103,9 +103,9 @@ impl Violation for SysVersionCmpStr10 {
}
}
define_violation!(
pub struct SysVersionSlice1Referenced;
);
#[violation]
pub struct SysVersionSlice1Referenced;
impl Violation for SysVersionSlice1Referenced {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt};
use super::fixes;
@ -15,30 +15,30 @@ use crate::violation::{AlwaysAutofixableViolation, Violation};
use crate::visibility;
use crate::visibility::Visibility;
define_violation!(
/// ## What it does
/// Checks that function arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(x):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(x: int):
/// ...
/// ```
pub struct MissingTypeFunctionArgument {
pub name: String,
}
);
/// ## What it does
/// Checks that function arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(x):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(x: int):
/// ...
/// ```
#[violation]
pub struct MissingTypeFunctionArgument {
pub name: String,
}
impl Violation for MissingTypeFunctionArgument {
#[derive_message_formats]
fn message(&self) -> String {
@ -47,30 +47,30 @@ impl Violation for MissingTypeFunctionArgument {
}
}
define_violation!(
/// ## What it does
/// Checks that function `*args` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(*args):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(*args: int):
/// ...
/// ```
pub struct MissingTypeArgs {
pub name: String,
}
);
/// ## What it does
/// Checks that function `*args` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(*args):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(*args: int):
/// ...
/// ```
#[violation]
pub struct MissingTypeArgs {
pub name: String,
}
impl Violation for MissingTypeArgs {
#[derive_message_formats]
fn message(&self) -> String {
@ -79,30 +79,30 @@ impl Violation for MissingTypeArgs {
}
}
define_violation!(
/// ## What it does
/// Checks that function `**kwargs` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(**kwargs):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(**kwargs: int):
/// ...
/// ```
pub struct MissingTypeKwargs {
pub name: String,
}
);
/// ## What it does
/// Checks that function `**kwargs` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// ## Example
/// ```python
/// def foo(**kwargs):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(**kwargs: int):
/// ...
/// ```
#[violation]
pub struct MissingTypeKwargs {
pub name: String,
}
impl Violation for MissingTypeKwargs {
#[derive_message_formats]
fn message(&self) -> String {
@ -111,35 +111,35 @@ impl Violation for MissingTypeKwargs {
}
}
define_violation!(
/// ## What it does
/// Checks that instance method `self` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// Note that many type checkers will infer the type of `self` automatically, so this
/// annotation is not strictly necessary.
///
/// ## Example
/// ```python
/// class Foo:
/// def bar(self):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// def bar(self: "Foo"):
/// ...
/// ```
pub struct MissingTypeSelf {
pub name: String,
}
);
/// ## What it does
/// Checks that instance method `self` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// Note that many type checkers will infer the type of `self` automatically, so this
/// annotation is not strictly necessary.
///
/// ## Example
/// ```python
/// class Foo:
/// def bar(self):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// def bar(self: "Foo"):
/// ...
/// ```
#[violation]
pub struct MissingTypeSelf {
pub name: String,
}
impl Violation for MissingTypeSelf {
#[derive_message_formats]
fn message(&self) -> String {
@ -148,37 +148,37 @@ impl Violation for MissingTypeSelf {
}
}
define_violation!(
/// ## What it does
/// Checks that class method `cls` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// Note that many type checkers will infer the type of `cls` automatically, so this
/// annotation is not strictly necessary.
///
/// ## Example
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls: Type["Foo"]):
/// ...
/// ```
pub struct MissingTypeCls {
pub name: String,
}
);
/// ## What it does
/// Checks that class method `cls` arguments have type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the types of function arguments. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any provided arguments match expectation.
///
/// Note that many type checkers will infer the type of `cls` automatically, so this
/// annotation is not strictly necessary.
///
/// ## Example
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls: Type["Foo"]):
/// ...
/// ```
#[violation]
pub struct MissingTypeCls {
pub name: String,
}
impl Violation for MissingTypeCls {
#[derive_message_formats]
fn message(&self) -> String {
@ -187,30 +187,30 @@ impl Violation for MissingTypeCls {
}
}
define_violation!(
/// ## What it does
/// Checks that public functions and methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// def add(a, b):
/// return a + b
/// ```
///
/// Use instead:
/// ```python
/// def add(a: int, b: int) -> int:
/// return a + b
/// ```
pub struct MissingReturnTypePublicFunction {
pub name: String,
}
);
/// ## What it does
/// Checks that public functions and methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// def add(a, b):
/// return a + b
/// ```
///
/// Use instead:
/// ```python
/// def add(a: int, b: int) -> int:
/// return a + b
/// ```
#[violation]
pub struct MissingReturnTypePublicFunction {
pub name: String,
}
impl Violation for MissingReturnTypePublicFunction {
#[derive_message_formats]
fn message(&self) -> String {
@ -219,30 +219,30 @@ impl Violation for MissingReturnTypePublicFunction {
}
}
define_violation!(
/// ## What it does
/// Checks that private functions and methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// def _add(a, b):
/// return a + b
/// ```
///
/// Use instead:
/// ```python
/// def _add(a: int, b: int) -> int:
/// return a + b
/// ```
pub struct MissingReturnTypePrivateFunction {
pub name: String,
}
);
/// ## What it does
/// Checks that private functions and methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// def _add(a, b):
/// return a + b
/// ```
///
/// Use instead:
/// ```python
/// def _add(a: int, b: int) -> int:
/// return a + b
/// ```
#[violation]
pub struct MissingReturnTypePrivateFunction {
pub name: String,
}
impl Violation for MissingReturnTypePrivateFunction {
#[derive_message_formats]
fn message(&self) -> String {
@ -251,43 +251,43 @@ impl Violation for MissingReturnTypePrivateFunction {
}
}
define_violation!(
/// ## What it does
/// Checks that "special" methods, like `__init__`, `__new__`, and `__call__`, have
/// return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// Note that type checkers often allow you to omit the return type annotation for
/// `__init__` methods, as long as at least one argument has a type annotation. To
/// opt-in to this behavior, use the `mypy-init-return` setting in your `pyproject.toml`
/// or `ruff.toml` file:
///
/// ```toml
/// [tool.ruff.flake8-annotations]
/// mypy-init-return = true
/// ```
///
/// ## Example
/// ```python
/// class Foo:
/// def __init__(self, x: int):
/// self.x = x
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// def __init__(self, x: int) -> None:
/// self.x = x
/// ```
pub struct MissingReturnTypeSpecialMethod {
pub name: String,
}
);
/// ## What it does
/// Checks that "special" methods, like `__init__`, `__new__`, and `__call__`, have
/// return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// Note that type checkers often allow you to omit the return type annotation for
/// `__init__` methods, as long as at least one argument has a type annotation. To
/// opt-in to this behavior, use the `mypy-init-return` setting in your `pyproject.toml`
/// or `ruff.toml` file:
///
/// ```toml
/// [tool.ruff.flake8-annotations]
/// mypy-init-return = true
/// ```
///
/// ## Example
/// ```python
/// class Foo:
/// def __init__(self, x: int):
/// self.x = x
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// def __init__(self, x: int) -> None:
/// self.x = x
/// ```
#[violation]
pub struct MissingReturnTypeSpecialMethod {
pub name: String,
}
impl AlwaysAutofixableViolation for MissingReturnTypeSpecialMethod {
#[derive_message_formats]
fn message(&self) -> String {
@ -300,34 +300,34 @@ impl AlwaysAutofixableViolation for MissingReturnTypeSpecialMethod {
}
}
define_violation!(
/// ## What it does
/// Checks that static methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// class Foo:
/// @staticmethod
/// def bar():
/// return 1
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @staticmethod
/// def bar() -> int:
/// return 1
/// ```
pub struct MissingReturnTypeStaticMethod {
pub name: String,
}
);
/// ## What it does
/// Checks that static methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// class Foo:
/// @staticmethod
/// def bar():
/// return 1
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @staticmethod
/// def bar() -> int:
/// return 1
/// ```
#[violation]
pub struct MissingReturnTypeStaticMethod {
pub name: String,
}
impl Violation for MissingReturnTypeStaticMethod {
#[derive_message_formats]
fn message(&self) -> String {
@ -336,34 +336,34 @@ impl Violation for MissingReturnTypeStaticMethod {
}
}
define_violation!(
/// ## What it does
/// Checks that class methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls):
/// return 1
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls) -> int:
/// return 1
/// ```
pub struct MissingReturnTypeClassMethod {
pub name: String,
}
);
/// ## What it does
/// Checks that class methods have return type annotations.
///
/// ## Why is this bad?
/// Type annotations are a good way to document the return types of functions. They also
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
/// any returned values, and the types expected by callers, match expectation.
///
/// ## Example
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls):
/// return 1
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// @classmethod
/// def bar(cls) -> int:
/// return 1
/// ```
#[violation]
pub struct MissingReturnTypeClassMethod {
pub name: String,
}
impl Violation for MissingReturnTypeClassMethod {
#[derive_message_formats]
fn message(&self) -> String {
@ -372,39 +372,39 @@ impl Violation for MissingReturnTypeClassMethod {
}
}
define_violation!(
/// ## What it does
/// Checks that an expression is annotated with a more specific type than
/// `Any`.
///
/// ## Why is this bad?
/// `Any` is a special type indicating an unconstrained type. When an
/// expression is annotated with type `Any`, type checkers will allow all
/// operations on it.
///
/// It's better to be explicit about the type of an expression, and to use
/// `Any` as an "escape hatch" only when it is really needed.
///
/// ## Example
/// ```python
/// def foo(x: Any):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(x: int):
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://www.python.org/dev/peps/pep-0484/#the-any-type)
/// - [`typing.Any`](https://docs.python.org/3/library/typing.html#typing.Any)
/// - [Mypy: The Any type](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-any-type)
pub struct AnyType {
pub name: String,
}
);
/// ## What it does
/// Checks that an expression is annotated with a more specific type than
/// `Any`.
///
/// ## Why is this bad?
/// `Any` is a special type indicating an unconstrained type. When an
/// expression is annotated with type `Any`, type checkers will allow all
/// operations on it.
///
/// It's better to be explicit about the type of an expression, and to use
/// `Any` as an "escape hatch" only when it is really needed.
///
/// ## Example
/// ```python
/// def foo(x: Any):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// def foo(x: int):
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://www.python.org/dev/peps/pep-0484/#the-any-type)
/// - [`typing.Any`](https://docs.python.org/3/library/typing.html#typing.Any)
/// - [Mypy: The Any type](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-any-type)
#[violation]
pub struct AnyType {
pub name: String,
}
impl Violation for AnyType {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,14 +1,14 @@
use rustpython_parser::ast::Stmt;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct Assert;
);
#[violation]
pub struct Assert;
impl Violation for Assert {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use num_traits::ToPrimitive;
use once_cell::sync::Lazy;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Operator};
@ -10,11 +10,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct BadFilePermissions {
pub mask: u16,
}
);
#[violation]
pub struct BadFilePermissions {
pub mask: u16,
}
impl Violation for BadFilePermissions {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,13 +1,13 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct ExecBuiltin;
);
#[violation]
pub struct ExecBuiltin;
impl Violation for ExecBuiltin {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,12 +1,12 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct HardcodedBindAllInterfaces;
);
#[violation]
pub struct HardcodedBindAllInterfaces;
impl Violation for HardcodedBindAllInterfaces {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Arg, Arguments, Expr};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
@ -8,11 +8,11 @@ use crate::violation::Violation;
use super::super::helpers::{matches_password_name, string_literal};
define_violation!(
pub struct HardcodedPasswordDefault {
pub string: String,
}
);
#[violation]
pub struct HardcodedPasswordDefault {
pub string: String,
}
impl Violation for HardcodedPasswordDefault {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Keyword;
use super::super::helpers::{matches_password_name, string_literal};
@ -6,11 +6,11 @@ use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct HardcodedPasswordFuncArg {
pub string: String,
}
);
#[violation]
pub struct HardcodedPasswordFuncArg {
pub string: String,
}
impl Violation for HardcodedPasswordFuncArg {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use super::super::helpers::{matches_password_name, string_literal};
@ -6,11 +6,11 @@ use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct HardcodedPasswordString {
pub string: String,
}
);
#[violation]
pub struct HardcodedPasswordString {
pub string: String,
}
impl Violation for HardcodedPasswordString {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use once_cell::sync::Lazy;
use regex::Regex;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Operator};
use super::super::helpers::string_literal;
@ -15,28 +15,28 @@ static SQL_REGEX: Lazy<Regex> = Lazy::new(|| {
.unwrap()
});
define_violation!(
/// ## What it does
/// Checks for strings that resemble SQL statements involved in some form
/// string building operation.
///
/// ## Why is this bad?
/// SQL injection is a common attack vector for web applications. Directly
/// interpolating user input into SQL statements should always be avoided.
/// Instead, favor parameterized queries, in which the SQL statement is
/// provided separately from its parameters, as supported by `psycopg3`
/// and other database drivers and ORMs.
///
/// ## Example
/// ```python
/// query = "DELETE FROM foo WHERE id = '%s'" % identifier
/// ```
///
/// ## References
/// - [B608: Test for SQL injection](https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html)
/// - [psycopg3: Server-side binding](https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html#server-side-binding)
pub struct HardcodedSQLExpression;
);
/// ## What it does
/// Checks for strings that resemble SQL statements involved in some form
/// string building operation.
///
/// ## Why is this bad?
/// SQL injection is a common attack vector for web applications. Directly
/// interpolating user input into SQL statements should always be avoided.
/// Instead, favor parameterized queries, in which the SQL statement is
/// provided separately from its parameters, as supported by `psycopg3`
/// and other database drivers and ORMs.
///
/// ## Example
/// ```python
/// query = "DELETE FROM foo WHERE id = '%s'" % identifier
/// ```
///
/// ## References
/// - [B608: Test for SQL injection](https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html)
/// - [psycopg3: Server-side binding](https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html#server-side-binding)
#[violation]
pub struct HardcodedSQLExpression;
impl Violation for HardcodedSQLExpression {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,15 +1,15 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Expr;
use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct HardcodedTempFile {
pub string: String,
}
);
#[violation]
pub struct HardcodedTempFile {
pub string: String,
}
impl Violation for HardcodedTempFile {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use super::super::helpers::string_literal;
@ -8,11 +8,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct HashlibInsecureHashFunction {
pub string: String,
}
);
#[violation]
pub struct HashlibInsecureHashFunction {
pub string: String,
}
impl Violation for HashlibInsecureHashFunction {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -7,11 +7,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct Jinja2AutoescapeFalse {
pub value: bool,
}
);
#[violation]
pub struct Jinja2AutoescapeFalse {
pub value: bool,
}
impl Violation for Jinja2AutoescapeFalse {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -7,9 +7,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct LoggingConfigInsecureListen;
);
#[violation]
pub struct LoggingConfigInsecureListen;
impl Violation for LoggingConfigInsecureListen {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -7,11 +7,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct RequestWithNoCertValidation {
pub string: String,
}
);
#[violation]
pub struct RequestWithNoCertValidation {
pub string: String,
}
impl Violation for RequestWithNoCertValidation {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::{unparse_constant, SimpleCallArgs};
@ -7,11 +7,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct RequestWithoutTimeout {
pub timeout: Option<String>,
}
);
#[violation]
pub struct RequestWithoutTimeout {
pub timeout: Option<String>,
}
impl Violation for RequestWithoutTimeout {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use num_traits::{One, Zero};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct SnmpInsecureVersion;
);
#[violation]
pub struct SnmpInsecureVersion;
impl Violation for SnmpInsecureVersion {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -7,9 +7,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct SnmpWeakCryptography;
);
#[violation]
pub struct SnmpWeakCryptography;
impl Violation for SnmpWeakCryptography {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Excepthandler, Expr, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -8,9 +8,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_bandit::helpers::is_untyped_exception;
use crate::violation::Violation;
define_violation!(
pub struct TryExceptContinue;
);
#[violation]
pub struct TryExceptContinue;
impl Violation for TryExceptContinue {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Excepthandler, Expr, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -8,9 +8,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_bandit::helpers::is_untyped_exception;
use crate::violation::Violation;
define_violation!(
pub struct TryExceptPass;
);
#[violation]
pub struct TryExceptPass;
impl Violation for TryExceptPass {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use crate::ast::helpers::SimpleCallArgs;
@ -7,11 +7,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UnsafeYAMLLoad {
pub loader: Option<String>,
}
);
#[violation]
pub struct UnsafeYAMLLoad {
pub loader: Option<String>,
}
impl Violation for UnsafeYAMLLoad {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use crate::ast::helpers;
@ -8,11 +8,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct BlindExcept {
pub name: String,
}
);
#[violation]
pub struct BlindExcept {
pub name: String,
}
impl Violation for BlindExcept {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::helpers::collect_call_path;
use crate::ast::types::Range;
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation;
define_violation!(
pub struct BooleanPositionalArgInFunctionDefinition;
);
#[violation]
pub struct BooleanPositionalArgInFunctionDefinition;
impl Violation for BooleanPositionalArgInFunctionDefinition {
#[derive_message_formats]
fn message(&self) -> String {
@ -18,9 +18,9 @@ impl Violation for BooleanPositionalArgInFunctionDefinition {
}
}
define_violation!(
pub struct BooleanDefaultValueInFunctionDefinition;
);
#[violation]
pub struct BooleanDefaultValueInFunctionDefinition;
impl Violation for BooleanDefaultValueInFunctionDefinition {
#[derive_message_formats]
fn message(&self) -> String {
@ -28,9 +28,9 @@ impl Violation for BooleanDefaultValueInFunctionDefinition {
}
}
define_violation!(
pub struct BooleanPositionalValueInFunctionCall;
);
#[violation]
pub struct BooleanPositionalValueInFunctionCall;
impl Violation for BooleanPositionalValueInFunctionCall {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
use crate::ast::types::Range;
@ -7,11 +7,11 @@ use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation;
use crate::visibility::{is_abstract, is_overload};
define_violation!(
pub struct AbstractBaseClassWithoutAbstractMethod {
pub name: String,
}
);
#[violation]
pub struct AbstractBaseClassWithoutAbstractMethod {
pub name: String,
}
impl Violation for AbstractBaseClassWithoutAbstractMethod {
#[derive_message_formats]
fn message(&self) -> String {
@ -19,11 +19,11 @@ impl Violation for AbstractBaseClassWithoutAbstractMethod {
format!("`{name}` is an abstract base class, but it has no abstract methods")
}
}
define_violation!(
pub struct EmptyMethodWithoutAbstractDecorator {
pub name: String,
}
);
#[violation]
pub struct EmptyMethodWithoutAbstractDecorator {
pub name: String,
}
impl Violation for EmptyMethodWithoutAbstractDecorator {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
use crate::ast::helpers::unparse_stmt;
@ -8,9 +8,9 @@ use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct AssertFalse;
);
#[violation]
pub struct AssertFalse;
impl AlwaysAutofixableViolation for AssertFalse {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{ExprKind, Stmt, Withitem};
use crate::ast::types::Range;
@ -6,28 +6,28 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for `self.assertRaises(Exception)`.
///
/// ## Why is this bad?
/// `assertRaises(Exception)` can lead to your test passing even if the
/// code being tested is never executed due to a typo.
///
/// Either assert for a more specific exception (builtin or custom), use
/// `assertRaisesRegex` or the context manager form of `assertRaises`.
///
/// ## Example
/// ```python
/// self.assertRaises(Exception, foo)
/// ```
///
/// Use instead:
/// ```python
/// self.assertRaises(SomeSpecificException, foo)
/// ```
pub struct AssertRaisesException;
);
/// ## What it does
/// Checks for `self.assertRaises(Exception)`.
///
/// ## Why is this bad?
/// `assertRaises(Exception)` can lead to your test passing even if the
/// code being tested is never executed due to a typo.
///
/// Either assert for a more specific exception (builtin or custom), use
/// `assertRaisesRegex` or the context manager form of `assertRaises`.
///
/// ## Example
/// ```python
/// self.assertRaises(Exception, foo)
/// ```
///
/// Use instead:
/// ```python
/// self.assertRaises(SomeSpecificException, foo)
/// ```
#[violation]
pub struct AssertRaisesException;
impl Violation for AssertRaisesException {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct AssignmentToOsEnviron;
);
#[violation]
pub struct AssignmentToOsEnviron;
impl Violation for AssignmentToOsEnviron {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::{Range, ScopeKind};
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct CachedInstanceMethod;
);
#[violation]
pub struct CachedInstanceMethod;
impl Violation for CachedInstanceMethod {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct CannotRaiseLiteral;
);
#[violation]
pub struct CannotRaiseLiteral;
impl Violation for CannotRaiseLiteral {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_parser::ast::{
Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location,
@ -13,11 +13,11 @@ use crate::fix::Fix;
use crate::registry::{Diagnostic, Rule};
use crate::violation::{AlwaysAutofixableViolation, Violation};
define_violation!(
pub struct DuplicateTryBlockException {
pub name: String,
}
);
#[violation]
pub struct DuplicateTryBlockException {
pub name: String,
}
impl Violation for DuplicateTryBlockException {
#[derive_message_formats]
fn message(&self) -> String {
@ -25,11 +25,11 @@ impl Violation for DuplicateTryBlockException {
format!("try-except block with duplicate exception `{name}`")
}
}
define_violation!(
pub struct DuplicateHandlerException {
pub names: Vec<String>,
}
);
#[violation]
pub struct DuplicateHandlerException {
pub names: Vec<String>,
}
impl AlwaysAutofixableViolation for DuplicateHandlerException {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Excepthandler;
use crate::ast::types::Range;
@ -8,9 +8,9 @@ use crate::violation::Violation;
use rustpython_parser::ast::{ExcepthandlerKind, ExprKind};
define_violation!(
pub struct ExceptWithEmptyTuple;
);
#[violation]
pub struct ExceptWithEmptyTuple;
impl Violation for ExceptWithEmptyTuple {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
use crate::ast::helpers;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct FStringDocstring;
);
#[violation]
pub struct FStringDocstring;
impl Violation for FStringDocstring {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
use super::mutable_argument_default::is_mutable_func;
@ -10,11 +10,11 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation;
define_violation!(
pub struct FunctionCallArgumentDefault {
pub name: Option<String>,
}
);
#[violation]
pub struct FunctionCallArgumentDefault {
pub name: Option<String>,
}
impl Violation for FunctionCallArgumentDefault {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashSet;
use rustpython_parser::ast::{Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind};
@ -10,11 +10,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct FunctionUsesLoopVariable {
pub name: String,
}
);
#[violation]
pub struct FunctionUsesLoopVariable {
pub name: String,
}
impl Violation for FunctionUsesLoopVariable {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use ruff_python::identifiers::{is_identifier, is_mangled_private};
use ruff_python::keyword::KWLIST;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location};
@ -10,9 +10,9 @@ use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct GetAttrWithConstant;
);
#[violation]
pub struct GetAttrWithConstant;
impl AlwaysAutofixableViolation for GetAttrWithConstant {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Stmt, StmtKind};
use crate::ast::types::Range;
@ -6,11 +6,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct JumpStatementInFinally {
pub name: String,
}
);
#[violation]
pub struct JumpStatementInFinally {
pub name: String,
}
impl Violation for JumpStatementInFinally {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind};
@ -9,11 +9,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct LoopVariableOverridesIterator {
pub name: String,
}
);
#[violation]
pub struct LoopVariableOverridesIterator {
pub name: String,
}
impl Violation for LoopVariableOverridesIterator {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind, Operator};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct MutableArgumentDefault;
);
#[violation]
pub struct MutableArgumentDefault;
impl Violation for MutableArgumentDefault {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{ExprKind, Stmt};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use ruff_python::str::is_lower;
use crate::ast::helpers::RaiseStatementVisitor;
@ -9,9 +9,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct RaiseWithoutFromInsideExcept;
);
#[violation]
pub struct RaiseWithoutFromInsideExcept;
impl Violation for RaiseWithoutFromInsideExcept {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, ExprKind};
use crate::ast::helpers::unparse_expr;
@ -8,11 +8,11 @@ use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct RedundantTupleInExceptionHandler {
pub name: String,
}
);
#[violation]
pub struct RedundantTupleInExceptionHandler {
pub name: String,
}
impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use ruff_python::identifiers::{is_identifier, is_mangled_private};
use ruff_python::keyword::KWLIST;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
@ -11,9 +11,9 @@ use crate::registry::Diagnostic;
use crate::source_code::Stylist;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct SetAttrWithConstant;
);
#[violation]
pub struct SetAttrWithConstant;
impl AlwaysAutofixableViolation for SetAttrWithConstant {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -7,7 +7,7 @@
//! by the unpacked sequence, and this change of ordering can surprise and
//! mislead readers.
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use crate::ast::types::Range;
@ -15,9 +15,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct StarArgUnpackingAfterKeywordArg;
);
#[violation]
pub struct StarArgUnpackingAfterKeywordArg;
impl Violation for StarArgUnpackingAfterKeywordArg {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use crate::ast::types::Range;
@ -7,9 +7,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct StripWithMultiCharacters;
);
#[violation]
pub struct StripWithMultiCharacters;
impl Violation for StripWithMultiCharacters {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -17,7 +17,7 @@
//! n += 1
//! ```
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Unaryop};
use crate::ast::types::Range;
@ -25,9 +25,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UnaryPrefixIncrement;
);
#[violation]
pub struct UnaryPrefixIncrement;
impl Violation for UnaryPrefixIncrement {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,31 +1,31 @@
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for the unintentional use of type annotations.
///
/// ## Why is this bad?
/// The use of a colon (`:`) in lieu of an assignment (`=`) can be syntactically valid, but
/// is almost certainly a mistake when used in a subscript or attribute assignment.
///
/// ## Example
/// ```python
/// a["b"]: 1
/// ```
///
/// Use instead:
/// ```python
/// a["b"] = 1
/// ```
pub struct UnintentionalTypeAnnotation;
);
/// ## What it does
/// Checks for the unintentional use of type annotations.
///
/// ## Why is this bad?
/// The use of a colon (`:`) in lieu of an assignment (`=`) can be syntactically valid, but
/// is almost certainly a mistake when used in a subscript or attribute assignment.
///
/// ## Example
/// ```python
/// a["b"]: 1
/// ```
///
/// Use instead:
/// ```python
/// a["b"] = 1
/// ```
#[violation]
pub struct UnintentionalTypeAnnotation;
impl Violation for UnintentionalTypeAnnotation {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UnreliableCallableCheck;
);
#[violation]
pub struct UnreliableCallableCheck;
impl Violation for UnreliableCallableCheck {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -18,7 +18,7 @@
//! method()
//! ```
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
use serde::{Deserialize, Serialize};
@ -37,20 +37,20 @@ pub enum Certainty {
Uncertain,
}
define_violation!(
pub struct UnusedLoopControlVariable {
/// The name of the loop control variable.
pub name: String,
/// The name to which the variable should be renamed, if it can be
/// safely renamed.
pub rename: Option<String>,
/// Whether the variable is certain to be unused in the loop body, or
/// merely suspect. A variable _may_ be used, but undetectably
/// so, if the loop incorporates by magic control flow (e.g.,
/// `locals()`).
pub certainty: Certainty,
}
);
#[violation]
pub struct UnusedLoopControlVariable {
/// The name of the loop control variable.
pub name: String,
/// The name to which the variable should be renamed, if it can be
/// safely renamed.
pub rename: Option<String>,
/// Whether the variable is certain to be unused in the loop body, or
/// merely suspect. A variable _may_ be used, but undetectably
/// so, if the loop incorporates by magic control flow (e.g.,
/// `locals()`).
pub certainty: Certainty,
}
impl Violation for UnusedLoopControlVariable {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UselessComparison;
);
#[violation]
pub struct UselessComparison;
impl Violation for UselessComparison {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Expr;
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UselessContextlibSuppress;
);
#[violation]
pub struct UselessContextlibSuppress;
impl Violation for UselessContextlibSuppress {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UselessExpression;
);
#[violation]
pub struct UselessExpression;
impl Violation for UselessExpression {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct ZipWithoutExplicitStrict;
);
#[violation]
pub struct ZipWithoutExplicitStrict;
impl Violation for ZipWithoutExplicitStrict {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use ruff_python::builtins::BUILTINS;
use rustpython_parser::ast::Located;
@ -7,49 +7,49 @@ use crate::ast::types::Range;
use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for variable (and function) assignments that use the same name
/// as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of a variable increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the variable for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// def find_max(list_of_lists):
/// max = 0
/// for flat_list in list_of_lists:
/// for value in flat_list:
/// max = max(max, value) # TypeError: 'int' object is not callable
/// return max
/// ```
///
/// Use instead:
/// ```python
/// def find_max(list_of_lists):
/// result = 0
/// for flat_list in list_of_lists:
/// for value in flat_list:
/// result = max(result, value)
/// return result
/// ```
///
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
pub struct BuiltinVariableShadowing {
pub name: String,
}
);
/// ## What it does
/// Checks for variable (and function) assignments that use the same name
/// as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of a variable increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the variable for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// def find_max(list_of_lists):
/// max = 0
/// for flat_list in list_of_lists:
/// for value in flat_list:
/// max = max(max, value) # TypeError: 'int' object is not callable
/// return max
/// ```
///
/// Use instead:
/// ```python
/// def find_max(list_of_lists):
/// result = 0
/// for flat_list in list_of_lists:
/// for value in flat_list:
/// result = max(result, value)
/// return result
/// ```
///
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
#[violation]
pub struct BuiltinVariableShadowing {
pub name: String,
}
impl Violation for BuiltinVariableShadowing {
#[derive_message_formats]
fn message(&self) -> String {
@ -58,52 +58,52 @@ impl Violation for BuiltinVariableShadowing {
}
}
define_violation!(
/// ## What it does
/// Checks for any function arguments that use the same name as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of an argument increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the argument for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// def remove_duplicates(list, list2):
/// result = set()
/// for value in list:
/// result.add(value)
/// for value in list2:
/// result.add(value)
/// return list(result) # TypeError: 'list' object is not callable
/// ```
///
/// Use instead:
/// ```python
/// def remove_duplicates(list1, list2):
/// result = set()
/// for value in list1:
/// result.add(value)
/// for value in list2:
/// result.add(value)
/// return list(result)
/// ```
///
/// ## References
/// - [_Is it bad practice to use a built-in function name as an attribute or method identifier?_](https://stackoverflow.com/questions/9109333/is-it-bad-practice-to-use-a-built-in-function-name-as-an-attribute-or-method-ide)
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
pub struct BuiltinArgumentShadowing {
pub name: String,
}
);
/// ## What it does
/// Checks for any function arguments that use the same name as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of an argument increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the argument for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// def remove_duplicates(list, list2):
/// result = set()
/// for value in list:
/// result.add(value)
/// for value in list2:
/// result.add(value)
/// return list(result) # TypeError: 'list' object is not callable
/// ```
///
/// Use instead:
/// ```python
/// def remove_duplicates(list1, list2):
/// result = set()
/// for value in list1:
/// result.add(value)
/// for value in list2:
/// result.add(value)
/// return list(result)
/// ```
///
/// ## References
/// - [_Is it bad practice to use a built-in function name as an attribute or method identifier?_](https://stackoverflow.com/questions/9109333/is-it-bad-practice-to-use-a-built-in-function-name-as-an-attribute-or-method-ide)
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
#[violation]
pub struct BuiltinArgumentShadowing {
pub name: String,
}
impl Violation for BuiltinArgumentShadowing {
#[derive_message_formats]
fn message(&self) -> String {
@ -112,53 +112,53 @@ impl Violation for BuiltinArgumentShadowing {
}
}
define_violation!(
/// ## What it does
/// Checks for any class attributes that use the same name as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of an attribute increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the attribute for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option, or
/// converted to the appropriate dunder method.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// class Shadow:
/// def int():
/// return 0
/// ```
///
/// Use instead:
/// ```python
/// class Shadow:
/// def to_int():
/// return 0
/// ```
///
/// Or:
/// ```python
/// class Shadow:
/// # Callable as `int(shadow)`
/// def __int__():
/// return 0
/// ```
///
/// ## References
/// - [_Is it bad practice to use a built-in function name as an attribute or method identifier?_](https://stackoverflow.com/questions/9109333/is-it-bad-practice-to-use-a-built-in-function-name-as-an-attribute-or-method-ide)
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
pub struct BuiltinAttributeShadowing {
pub name: String,
}
);
/// ## What it does
/// Checks for any class attributes that use the same name as a builtin.
///
/// ## Why is this bad?
/// Reusing a builtin name for the name of an attribute increases the
/// difficulty of reading and maintaining the code, and can cause
/// non-obvious errors, as readers may mistake the attribute for the
/// builtin and vice versa.
///
/// Builtins can be marked as exceptions to this rule via the
/// [`flake8-builtins.builtins-ignorelist`] configuration option, or
/// converted to the appropriate dunder method.
///
/// ## Options
///
/// - `flake8-builtins.builtins-ignorelist`
///
/// ## Example
/// ```python
/// class Shadow:
/// def int():
/// return 0
/// ```
///
/// Use instead:
/// ```python
/// class Shadow:
/// def to_int():
/// return 0
/// ```
///
/// Or:
/// ```python
/// class Shadow:
/// # Callable as `int(shadow)`
/// def __int__():
/// return 0
/// ```
///
/// ## References
/// - [_Is it bad practice to use a built-in function name as an attribute or method identifier?_](https://stackoverflow.com/questions/9109333/is-it-bad-practice-to-use-a-built-in-function-name-as-an-attribute-or-method-ide)
/// - [_Why is it a bad idea to name a variable `id` in Python?_](https://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python)
#[violation]
pub struct BuiltinAttributeShadowing {
pub name: String,
}
impl Violation for BuiltinAttributeShadowing {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::lexer::{LexResult, Spanned};
use rustpython_parser::Tok;
@ -109,9 +109,9 @@ impl Context {
}
}
define_violation!(
pub struct TrailingCommaMissing;
);
#[violation]
pub struct TrailingCommaMissing;
impl AlwaysAutofixableViolation for TrailingCommaMissing {
#[derive_message_formats]
fn message(&self) -> String {
@ -123,9 +123,9 @@ impl AlwaysAutofixableViolation for TrailingCommaMissing {
}
}
define_violation!(
pub struct TrailingCommaOnBareTupleProhibited;
);
#[violation]
pub struct TrailingCommaOnBareTupleProhibited;
impl Violation for TrailingCommaOnBareTupleProhibited {
#[derive_message_formats]
fn message(&self) -> String {
@ -133,9 +133,9 @@ impl Violation for TrailingCommaOnBareTupleProhibited {
}
}
define_violation!(
pub struct TrailingCommaProhibited;
);
#[violation]
pub struct TrailingCommaProhibited;
impl AlwaysAutofixableViolation for TrailingCommaProhibited {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use super::helpers;
@ -9,34 +9,34 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
/// ## What it does
/// Checks for unnecessary `list` or `reversed` calls around `sorted`
/// calls.
///
/// ## Why is this bad?
/// It is unnecessary to use `list` around `sorted`, as the latter already
/// returns a list.
///
/// It is also unnecessary to use `reversed` around `sorted`, as the latter
/// has a `reverse` argument that can be used in lieu of an additional
/// `reversed` call.
///
/// In both cases, it's clearer to avoid the redundant call.
///
/// ## Examples
/// ```python
/// reversed(sorted(iterable))
/// ```
///
/// Use instead:
/// ```python
/// sorted(iterable, reverse=True)
/// ```
pub struct UnnecessaryCallAroundSorted {
pub func: String,
}
);
/// ## What it does
/// Checks for unnecessary `list` or `reversed` calls around `sorted`
/// calls.
///
/// ## Why is this bad?
/// It is unnecessary to use `list` around `sorted`, as the latter already
/// returns a list.
///
/// It is also unnecessary to use `reversed` around `sorted`, as the latter
/// has a `reverse` argument that can be used in lieu of an additional
/// `reversed` call.
///
/// In both cases, it's clearer to avoid the redundant call.
///
/// ## Examples
/// ```python
/// reversed(sorted(iterable))
/// ```
///
/// Use instead:
/// ```python
/// sorted(iterable, reverse=True)
/// ```
#[violation]
pub struct UnnecessaryCallAroundSorted {
pub func: String,
}
impl AlwaysAutofixableViolation for UnnecessaryCallAroundSorted {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, Keyword};
use super::helpers;
@ -10,11 +10,11 @@ use crate::rules::flake8_comprehensions::fixes;
use crate::rules::flake8_comprehensions::settings::Settings;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryCollectionCall {
pub obj_type: String,
}
);
#[violation]
pub struct UnnecessaryCollectionCall {
pub obj_type: String,
}
impl AlwaysAutofixableViolation for UnnecessaryCollectionCall {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Comprehension, Expr, ExprKind};
use super::helpers;
@ -9,11 +9,11 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryComprehension {
pub obj_type: String,
}
);
#[violation]
pub struct UnnecessaryComprehension {
pub obj_type: String,
}
impl AlwaysAutofixableViolation for UnnecessaryComprehension {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Expr, ExprKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -10,46 +10,46 @@ use crate::violation::AlwaysAutofixableViolation;
use super::helpers;
define_violation!(
/// ## What it does
/// Checks for unnecessary `list`, `reversed`, `set`, `sorted`, and `tuple`
/// call within `list`, `set`, `sorted`, and `tuple` calls.
///
/// ## Why is this bad?
/// It's unnecessary to double-cast or double-process iterables by wrapping
/// the listed functions within an additional `list`, `set`, `sorted`, or
/// `tuple` call. Doing so is redundant and can be confusing for readers.
///
/// ## Examples
/// ```python
/// list(tuple(iterable))
/// ```
///
/// Use instead:
/// ```python
/// list(iterable)
/// ```
///
/// This rule applies to a variety of functions, including `list`, `reversed`,
/// `set`, `sorted`, and `tuple`. For example:
/// - Instead of `list(list(iterable))`, use `list(iterable)`.
/// - Instead of `list(tuple(iterable))`, use `list(iterable)`.
/// - Instead of `tuple(list(iterable))`, use `tuple(iterable)`.
/// - Instead of `tuple(tuple(iterable))`, use `tuple(iterable)`.
/// - Instead of `set(set(iterable))`, use `set(iterable)`.
/// - Instead of `set(list(iterable))`, use `set(iterable)`.
/// - Instead of `set(tuple(iterable))`, use `set(iterable)`.
/// - Instead of `set(sorted(iterable))`, use `set(iterable)`.
/// - Instead of `set(reversed(iterable))`, use `set(iterable)`.
/// - Instead of `sorted(list(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(tuple(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(sorted(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(reversed(iterable))`, use `sorted(iterable)`.
pub struct UnnecessaryDoubleCastOrProcess {
pub inner: String,
pub outer: String,
}
);
/// ## What it does
/// Checks for unnecessary `list`, `reversed`, `set`, `sorted`, and `tuple`
/// call within `list`, `set`, `sorted`, and `tuple` calls.
///
/// ## Why is this bad?
/// It's unnecessary to double-cast or double-process iterables by wrapping
/// the listed functions within an additional `list`, `set`, `sorted`, or
/// `tuple` call. Doing so is redundant and can be confusing for readers.
///
/// ## Examples
/// ```python
/// list(tuple(iterable))
/// ```
///
/// Use instead:
/// ```python
/// list(iterable)
/// ```
///
/// This rule applies to a variety of functions, including `list`, `reversed`,
/// `set`, `sorted`, and `tuple`. For example:
/// - Instead of `list(list(iterable))`, use `list(iterable)`.
/// - Instead of `list(tuple(iterable))`, use `list(iterable)`.
/// - Instead of `tuple(list(iterable))`, use `tuple(iterable)`.
/// - Instead of `tuple(tuple(iterable))`, use `tuple(iterable)`.
/// - Instead of `set(set(iterable))`, use `set(iterable)`.
/// - Instead of `set(list(iterable))`, use `set(iterable)`.
/// - Instead of `set(tuple(iterable))`, use `set(iterable)`.
/// - Instead of `set(sorted(iterable))`, use `set(iterable)`.
/// - Instead of `set(reversed(iterable))`, use `set(iterable)`.
/// - Instead of `sorted(list(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(tuple(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(sorted(iterable))`, use `sorted(iterable)`.
/// - Instead of `sorted(reversed(iterable))`, use `sorted(iterable)`.
#[violation]
pub struct UnnecessaryDoubleCastOrProcess {
pub inner: String,
pub outer: String,
}
impl AlwaysAutofixableViolation for UnnecessaryDoubleCastOrProcess {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,27 +9,27 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `dict`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `dict` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// dict((x, f(x)) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// {x: f(x) for x in foo}
/// ```
pub struct UnnecessaryGeneratorDict;
);
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `dict`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `dict` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// dict((x, f(x)) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// {x: f(x) for x in foo}
/// ```
#[violation]
pub struct UnnecessaryGeneratorDict;
impl AlwaysAutofixableViolation for UnnecessaryGeneratorDict {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,27 +9,27 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `list`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `list` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// list(f(x) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// [f(x) for x in foo]
/// ```
pub struct UnnecessaryGeneratorList;
);
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `list`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `list` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// list(f(x) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// [f(x) for x in foo]
/// ```
#[violation]
pub struct UnnecessaryGeneratorList;
impl AlwaysAutofixableViolation for UnnecessaryGeneratorList {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,27 +9,27 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `set`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `set` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// set(f(x) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// {f(x) for x in foo}
/// ```
pub struct UnnecessaryGeneratorSet;
);
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `set`
/// comprehensions.
///
/// ## Why is this bad?
/// It is unnecessary to use `set` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// ## Examples
/// ```python
/// set(f(x) for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// {f(x) for x in foo}
/// ```
#[violation]
pub struct UnnecessaryGeneratorSet;
impl AlwaysAutofixableViolation for UnnecessaryGeneratorSet {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use super::helpers;
@ -9,9 +9,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryListCall;
);
#[violation]
pub struct UnnecessaryListCall;
impl AlwaysAutofixableViolation for UnnecessaryListCall {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,9 +9,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryListComprehensionDict;
);
#[violation]
pub struct UnnecessaryListComprehensionDict;
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionDict {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,9 +9,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryListComprehensionSet;
);
#[violation]
pub struct UnnecessaryListComprehensionSet;
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionSet {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,11 +9,11 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryLiteralDict {
pub obj_type: String,
}
);
#[violation]
pub struct UnnecessaryLiteralDict {
pub obj_type: String,
}
impl AlwaysAutofixableViolation for UnnecessaryLiteralDict {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use super::helpers;
@ -9,11 +9,11 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryLiteralSet {
pub obj_type: String,
}
);
#[violation]
pub struct UnnecessaryLiteralSet {
pub obj_type: String,
}
impl AlwaysAutofixableViolation for UnnecessaryLiteralSet {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use super::helpers;
@ -9,11 +9,11 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryLiteralWithinListCall {
pub literal: String,
}
);
#[violation]
pub struct UnnecessaryLiteralWithinListCall {
pub literal: String,
}
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinListCall {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use super::helpers;
@ -9,11 +9,11 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_comprehensions::fixes;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct UnnecessaryLiteralWithinTupleCall {
pub literal: String,
}
);
#[violation]
pub struct UnnecessaryLiteralWithinTupleCall {
pub literal: String,
}
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinTupleCall {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,7 +1,7 @@
use log::error;
use rustpython_parser::ast::{Expr, ExprKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -11,37 +11,37 @@ use crate::violation::{AutofixKind, Availability, Violation};
use super::helpers;
define_violation!(
/// ## What it does
/// Checks for unnecessary `map` calls with `lambda` functions.
///
/// ## Why is this bad?
/// Using `map(func, iterable)` when `func` is a `lambda` is slower than
/// using a generator expression or a comprehension, as the latter approach
/// avoids the function call overhead, in addition to being more readable.
///
/// ## Examples
/// ```python
/// map(lambda x: x + 1, iterable)
/// ```
///
/// Use instead:
/// ```python
/// (x + 1 for x in iterable)
/// ```
///
/// This rule also applies to `map` calls within `list`, `set`, and `dict`
/// calls. For example:
/// - Instead of `list(map(lambda num: num * 2, nums))`, use
/// `[num * 2 for num in nums]`.
/// - Instead of `set(map(lambda num: num % 2 == 0, nums))`, use
/// `{num % 2 == 0 for num in nums}`.
/// - Instead of `dict(map(lambda v: (v, v ** 2), values))`, use
/// `{v: v ** 2 for v in values}`.
pub struct UnnecessaryMap {
pub obj_type: String,
}
);
/// ## What it does
/// Checks for unnecessary `map` calls with `lambda` functions.
///
/// ## Why is this bad?
/// Using `map(func, iterable)` when `func` is a `lambda` is slower than
/// using a generator expression or a comprehension, as the latter approach
/// avoids the function call overhead, in addition to being more readable.
///
/// ## Examples
/// ```python
/// map(lambda x: x + 1, iterable)
/// ```
///
/// Use instead:
/// ```python
/// (x + 1 for x in iterable)
/// ```
///
/// This rule also applies to `map` calls within `list`, `set`, and `dict`
/// calls. For example:
/// - Instead of `list(map(lambda num: num * 2, nums))`, use
/// `[num * 2 for num in nums]`.
/// - Instead of `set(map(lambda num: num % 2 == 0, nums))`, use
/// `{num % 2 == 0 for num in nums}`.
/// - Instead of `dict(map(lambda v: (v, v ** 2), values))`, use
/// `{v: v ** 2 for v in values}`.
#[violation]
pub struct UnnecessaryMap {
pub obj_type: String,
}
impl Violation for UnnecessaryMap {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Unaryop};
use super::helpers;
@ -8,11 +8,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct UnnecessarySubscriptReversal {
pub func: String,
}
);
#[violation]
pub struct UnnecessarySubscriptReversal {
pub func: String,
}
impl Violation for UnnecessarySubscriptReversal {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::{has_non_none_keyword, is_const_none};
@ -7,9 +7,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct CallDatetimeWithoutTzinfo;
);
#[violation]
pub struct CallDatetimeWithoutTzinfo;
impl Violation for CallDatetimeWithoutTzinfo {
#[derive_message_formats]
fn message(&self) -> String {
@ -17,9 +17,9 @@ impl Violation for CallDatetimeWithoutTzinfo {
}
}
define_violation!(
pub struct CallDatetimeToday;
);
#[violation]
pub struct CallDatetimeToday;
impl Violation for CallDatetimeToday {
#[derive_message_formats]
fn message(&self) -> String {
@ -30,9 +30,9 @@ impl Violation for CallDatetimeToday {
}
}
define_violation!(
pub struct CallDatetimeUtcnow;
);
#[violation]
pub struct CallDatetimeUtcnow;
impl Violation for CallDatetimeUtcnow {
#[derive_message_formats]
fn message(&self) -> String {
@ -43,9 +43,9 @@ impl Violation for CallDatetimeUtcnow {
}
}
define_violation!(
pub struct CallDatetimeUtcfromtimestamp;
);
#[violation]
pub struct CallDatetimeUtcfromtimestamp;
impl Violation for CallDatetimeUtcfromtimestamp {
#[derive_message_formats]
fn message(&self) -> String {
@ -56,9 +56,9 @@ impl Violation for CallDatetimeUtcfromtimestamp {
}
}
define_violation!(
pub struct CallDatetimeNowWithoutTzinfo;
);
#[violation]
pub struct CallDatetimeNowWithoutTzinfo;
impl Violation for CallDatetimeNowWithoutTzinfo {
#[derive_message_formats]
fn message(&self) -> String {
@ -66,9 +66,9 @@ impl Violation for CallDatetimeNowWithoutTzinfo {
}
}
define_violation!(
pub struct CallDatetimeFromtimestamp;
);
#[violation]
pub struct CallDatetimeFromtimestamp;
impl Violation for CallDatetimeFromtimestamp {
#[derive_message_formats]
fn message(&self) -> String {
@ -78,9 +78,9 @@ impl Violation for CallDatetimeFromtimestamp {
}
}
define_violation!(
pub struct CallDatetimeStrptimeWithoutZone;
);
#[violation]
pub struct CallDatetimeStrptimeWithoutZone;
impl Violation for CallDatetimeStrptimeWithoutZone {
#[derive_message_formats]
fn message(&self) -> String {
@ -91,9 +91,9 @@ impl Violation for CallDatetimeStrptimeWithoutZone {
}
}
define_violation!(
pub struct CallDateToday;
);
#[violation]
pub struct CallDateToday;
impl Violation for CallDateToday {
#[derive_message_formats]
fn message(&self) -> String {
@ -104,9 +104,9 @@ impl Violation for CallDateToday {
}
}
define_violation!(
pub struct CallDateFromtimestamp;
);
#[violation]
pub struct CallDateFromtimestamp;
impl Violation for CallDateFromtimestamp {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, Stmt};
use super::types::DebuggerUsingType;
@ -10,11 +10,11 @@ use crate::violation::Violation;
// flake8-debugger
define_violation!(
pub struct Debugger {
pub using_type: DebuggerUsingType,
}
);
#[violation]
pub struct Debugger {
pub using_type: DebuggerUsingType,
}
impl Violation for Debugger {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,44 +1,44 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::rules::flake8_django::rules::helpers::is_model_form;
use crate::violation::Violation;
use crate::{checkers::ast::Checker, registry::Diagnostic, Range};
define_violation!(
/// ## What it does
/// Checks for the use of `fields = "__all__"` in Django `ModelForm`
/// classes.
///
/// ## Why is this bad?
/// If a `ModelForm` includes the `fields = "__all__"` attribute, any new
/// field that is added to the model will automatically be exposed for
/// modification.
///
/// ## Example
/// ```python
/// from django.forms import ModelForm
///
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = "__all__"
/// ```
///
/// Use instead:
/// ```python
/// from django.forms import ModelForm
///
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = ["title", "content"]
/// ```
pub struct AllWithModelForm;
);
/// ## What it does
/// Checks for the use of `fields = "__all__"` in Django `ModelForm`
/// classes.
///
/// ## Why is this bad?
/// If a `ModelForm` includes the `fields = "__all__"` attribute, any new
/// field that is added to the model will automatically be exposed for
/// modification.
///
/// ## Example
/// ```python
/// from django.forms import ModelForm
///
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = "__all__"
/// ```
///
/// Use instead:
/// ```python
/// from django.forms import ModelForm
///
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = ["title", "content"]
/// ```
#[violation]
pub struct AllWithModelForm;
impl Violation for AllWithModelForm {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,40 +1,40 @@
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::rules::flake8_django::rules::helpers::is_model_form;
use crate::violation::Violation;
use crate::{checkers::ast::Checker, registry::Diagnostic, Range};
define_violation!(
/// ## What it does
/// Checks for the use of `exclude` in Django `ModelForm` classes.
///
/// ## Why is this bad?
/// If a `ModelForm` includes the `exclude` attribute, any new field that
/// is added to the model will automatically be exposed for modification.
///
/// ## Example
/// ```python
/// from django.forms import ModelForm
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// exclude = ["author"]
/// ```
///
/// Use instead:
/// ```python
/// from django.forms import ModelForm
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = ["title", "content"]
/// ```
pub struct ExcludeWithModelForm;
);
/// ## What it does
/// Checks for the use of `exclude` in Django `ModelForm` classes.
///
/// ## Why is this bad?
/// If a `ModelForm` includes the `exclude` attribute, any new field that
/// is added to the model will automatically be exposed for modification.
///
/// ## Example
/// ```python
/// from django.forms import ModelForm
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// exclude = ["author"]
/// ```
///
/// Use instead:
/// ```python
/// from django.forms import ModelForm
///
/// class PostForm(ModelForm):
/// class Meta:
/// model = Post
/// fields = ["title", "content"]
/// ```
#[violation]
pub struct ExcludeWithModelForm;
impl Violation for ExcludeWithModelForm {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,37 +1,37 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::{checkers::ast::Checker, registry::Diagnostic, violation::Violation, Range};
define_violation!(
/// ## What it does
/// Checks for the use of `locals()` in `render` functions.
///
/// ## Why is this bad?
/// Using `locals()` can expose internal variables or other unintentional
/// data to the rendered template.
///
/// ## Example
/// ```python
/// from django.shortcuts import render
///
/// def index(request):
/// posts = Post.objects.all()
/// return render(request, "app/index.html", locals())
/// ```
///
/// Use instead:
/// ```python
/// from django.shortcuts import render
///
/// def index(request):
/// posts = Post.objects.all()
/// context = {"posts": posts}
/// return render(request, "app/index.html", context)
/// ```
pub struct LocalsInRenderFunction;
);
/// ## What it does
/// Checks for the use of `locals()` in `render` functions.
///
/// ## Why is this bad?
/// Using `locals()` can expose internal variables or other unintentional
/// data to the rendered template.
///
/// ## Example
/// ```python
/// from django.shortcuts import render
///
/// def index(request):
/// posts = Post.objects.all()
/// return render(request, "app/index.html", locals())
/// ```
///
/// Use instead:
/// ```python
/// from django.shortcuts import render
///
/// def index(request):
/// posts = Post.objects.all()
/// context = {"posts": posts}
/// return render(request, "app/index.html", context)
/// ```
#[violation]
pub struct LocalsInRenderFunction;
impl Violation for LocalsInRenderFunction {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,7 +1,7 @@
use rustpython_parser::ast::{Constant, Expr, StmtKind};
use rustpython_parser::ast::{ExprKind, Stmt};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -10,40 +10,40 @@ use crate::violation::Violation;
use super::helpers;
define_violation!(
/// ## What it does
/// Checks that `__str__` method is defined in Django models.
///
/// ## Why is this bad?
/// Django models should define `__str__` method to return a string representation
/// of the model instance, as Django calls this method to display the object in
/// the Django Admin and elsewhere.
///
/// Models without `__str__` method will display a non-meaningful representation
/// of the object in the Django Admin.
///
/// ## Example
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255)
/// ```
///
/// Use instead:
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255)
///
/// def __str__(self):
/// return f"{self.field}"
/// ```
pub struct ModelWithoutDunderStr;
);
/// ## What it does
/// Checks that `__str__` method is defined in Django models.
///
/// ## Why is this bad?
/// Django models should define `__str__` method to return a string representation
/// of the model instance, as Django calls this method to display the object in
/// the Django Admin and elsewhere.
///
/// Models without `__str__` method will display a non-meaningful representation
/// of the object in the Django Admin.
///
/// ## Example
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255)
/// ```
///
/// Use instead:
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255)
///
/// def __str__(self):
/// return f"{self.field}"
/// ```
#[violation]
pub struct ModelWithoutDunderStr;
impl Violation for ModelWithoutDunderStr {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,47 +1,47 @@
use rustpython_parser::ast::{Expr, ExprKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::{CallPath, Range};
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks that Django's `@receiver` decorator is listed first, prior to
/// any other decorators.
///
/// ## Why is this bad?
/// Django's `@receiver` decorator is special in that it does not return
/// a wrapped function. Rather, `@receiver` connects the decorated function
/// to a signal. If any other decorators are listed before `@receiver`,
/// the decorated function will not be connected to the signal.
///
/// ## Example
/// ```python
/// from django.dispatch import receiver
/// from django.db.models.signals import post_save
///
///
/// @transaction.atomic
/// @receiver(post_save, sender=MyModel)
/// def my_handler(sender, instance, created, **kwargs):
/// pass
/// ```
///
/// Use instead:
/// ```python
/// from django.dispatch import receiver
/// from django.db.models.signals import post_save
///
///
/// @receiver(post_save, sender=MyModel)
/// @transaction.atomic
/// def my_handler(sender, instance, created, **kwargs):
/// pass
/// ```
pub struct NonLeadingReceiverDecorator;
);
/// ## What it does
/// Checks that Django's `@receiver` decorator is listed first, prior to
/// any other decorators.
///
/// ## Why is this bad?
/// Django's `@receiver` decorator is special in that it does not return
/// a wrapped function. Rather, `@receiver` connects the decorated function
/// to a signal. If any other decorators are listed before `@receiver`,
/// the decorated function will not be connected to the signal.
///
/// ## Example
/// ```python
/// from django.dispatch import receiver
/// from django.db.models.signals import post_save
///
///
/// @transaction.atomic
/// @receiver(post_save, sender=MyModel)
/// def my_handler(sender, instance, created, **kwargs):
/// pass
/// ```
///
/// Use instead:
/// ```python
/// from django.dispatch import receiver
/// from django.db.models.signals import post_save
///
///
/// @receiver(post_save, sender=MyModel)
/// @transaction.atomic
/// def my_handler(sender, instance, created, **kwargs):
/// pass
/// ```
#[violation]
pub struct NonLeadingReceiverDecorator;
impl Violation for NonLeadingReceiverDecorator {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,7 +1,7 @@
use rustpython_parser::ast::Constant::Bool;
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
@ -10,41 +10,41 @@ use crate::violation::Violation;
use super::helpers;
define_violation!(
/// ## What it does
/// Checks nullable string-based fields (like `CharField` and `TextField`)
/// in Django models.
///
/// ## Why is this bad?
/// If a string-based field is nullable, then your model will have two possible
/// representations for "no data": `None` and the empty string. This can lead to
/// confusion, as clients of the API have to check for both `None` and the
/// empty string when trying to determine if the field has data.
///
/// The Django convention is to use the empty string in lieu of `None` for
/// string-based fields.
///
/// ## Example
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255, null=True)
/// ```
///
/// Use instead:
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255, default="")
/// ```
pub struct NullableModelStringField {
pub field_name: String,
}
);
/// ## What it does
/// Checks nullable string-based fields (like `CharField` and `TextField`)
/// in Django models.
///
/// ## Why is this bad?
/// If a string-based field is nullable, then your model will have two possible
/// representations for "no data": `None` and the empty string. This can lead to
/// confusion, as clients of the API have to check for both `None` and the
/// empty string when trying to determine if the field has data.
///
/// The Django convention is to use the empty string in lieu of `None` for
/// string-based fields.
///
/// ## Example
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255, null=True)
/// ```
///
/// Use instead:
/// ```python
/// from django.db import models
///
///
/// class MyModel(models.Model):
/// field = models.CharField(max_length=255, default="")
/// ```
#[violation]
pub struct NullableModelStringField {
pub field_name: String,
}
impl Violation for NullableModelStringField {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use crate::ast::types::Range;
@ -6,46 +6,46 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for the use of string literals in exception constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using a string literal, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// raise RuntimeError("'Some value' is incorrect")
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError("Some value is incorrect")
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// msg = "'Some value' is incorrect"
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
pub struct RawStringInException;
);
/// ## What it does
/// Checks for the use of string literals in exception constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using a string literal, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// raise RuntimeError("'Some value' is incorrect")
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError("Some value is incorrect")
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// msg = "'Some value' is incorrect"
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
#[violation]
pub struct RawStringInException;
impl Violation for RawStringInException {
#[derive_message_formats]
fn message(&self) -> String {
@ -53,47 +53,47 @@ impl Violation for RawStringInException {
}
}
define_violation!(
/// ## What it does
/// Checks for the use of f-strings in exception constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using an f-string, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// sub = "Some value"
/// raise RuntimeError(f"{sub!r} is incorrect")
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError(f"{sub!r} is incorrect")
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// sub = "Some value"
/// msg = f"{sub!r} is incorrect"
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
pub struct FStringInException;
);
/// ## What it does
/// Checks for the use of f-strings in exception constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using an f-string, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// sub = "Some value"
/// raise RuntimeError(f"{sub!r} is incorrect")
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError(f"{sub!r} is incorrect")
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// sub = "Some value"
/// msg = f"{sub!r} is incorrect"
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
#[violation]
pub struct FStringInException;
impl Violation for FStringInException {
#[derive_message_formats]
fn message(&self) -> String {
@ -101,49 +101,49 @@ impl Violation for FStringInException {
}
}
define_violation!(
/// ## What it does
/// Checks for the use of `.format` calls on string literals in exception
/// constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using a `.format` call, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// sub = "Some value"
/// raise RuntimeError("'{}' is incorrect".format(sub))
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError("'{}' is incorrect".format(sub))
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// sub = "Some value"
/// msg = "'{}' is incorrect".format(sub)
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
pub struct DotFormatInException;
);
/// ## What it does
/// Checks for the use of `.format` calls on string literals in exception
/// constructors.
///
/// ## Why is this bad?
/// Python includes the `raise` in the default traceback (and formatters
/// like Rich and IPython do too).
///
/// By using a `.format` call, the error message will be duplicated in the
/// traceback, which can make the traceback less readable.
///
/// ## Example
/// Given:
/// ```python
/// sub = "Some value"
/// raise RuntimeError("'{}' is incorrect".format(sub))
/// ```
///
/// Python will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 2, in <module>
/// raise RuntimeError("'{}' is incorrect".format(sub))
/// RuntimeError: 'Some value' is incorrect
/// ```
///
/// Instead, assign the string to a variable:
/// ```python
/// sub = "Some value"
/// msg = "'{}' is incorrect".format(sub)
/// raise RuntimeError(msg)
/// ```
///
/// Which will produce a traceback like:
/// ```console
/// Traceback (most recent call last):
/// File "tmp.py", line 3, in <module>
/// raise RuntimeError(msg)
/// RuntimeError: 'Some value' is incorrect
/// ```
#[violation]
pub struct DotFormatInException;
impl Violation for DotFormatInException {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -2,7 +2,7 @@
use std::path::Path;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
@ -10,9 +10,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::is_executable;
use crate::violation::Violation;
define_violation!(
pub struct ShebangMissingExecutableFile;
);
#[violation]
pub struct ShebangMissingExecutableFile;
impl Violation for ShebangMissingExecutableFile {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Location;
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation;
define_violation!(
pub struct ShebangNewline;
);
#[violation]
pub struct ShebangNewline;
impl Violation for ShebangNewline {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -4,7 +4,7 @@ use std::path::Path;
use rustpython_parser::ast::Location;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::registry::Diagnostic;
@ -13,9 +13,9 @@ use crate::rules::flake8_executable::helpers::is_executable;
use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation;
define_violation!(
pub struct ShebangNotExecutable;
);
#[violation]
pub struct ShebangNotExecutable;
impl Violation for ShebangNotExecutable {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Location;
use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation;
define_violation!(
pub struct ShebangPython;
);
#[violation]
pub struct ShebangPython;
impl Violation for ShebangPython {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::Location;
use crate::ast::types::Range;
@ -7,9 +7,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::AlwaysAutofixableViolation;
define_violation!(
pub struct ShebangWhitespace;
);
#[violation]
pub struct ShebangWhitespace;
impl AlwaysAutofixableViolation for ShebangWhitespace {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
use rustpython_parser::lexer::LexResult;
use rustpython_parser::Tok;
@ -9,30 +9,30 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_implicit_str_concat::settings::Settings;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for implicitly concatenated strings on a single line.
///
/// ## Why is this bad?
/// While it is valid Python syntax to concatenate multiple string or byte
/// literals implicitly (via whitespace delimiters), it is unnecessary and
/// negatively affects code readability.
///
/// In some cases, the implicit concatenation may also be unintentional, as
/// autoformatters are capable of introducing single-line implicit
/// concatenations when collapsing long lines.
///
/// ## Example
/// ```python
/// z = "The quick " "brown fox."
/// ```
///
/// Use instead:
/// ```python
/// z = "The quick brown fox."
/// ```
pub struct SingleLineImplicitStringConcatenation;
);
/// ## What it does
/// Checks for implicitly concatenated strings on a single line.
///
/// ## Why is this bad?
/// While it is valid Python syntax to concatenate multiple string or byte
/// literals implicitly (via whitespace delimiters), it is unnecessary and
/// negatively affects code readability.
///
/// In some cases, the implicit concatenation may also be unintentional, as
/// autoformatters are capable of introducing single-line implicit
/// concatenations when collapsing long lines.
///
/// ## Example
/// ```python
/// z = "The quick " "brown fox."
/// ```
///
/// Use instead:
/// ```python
/// z = "The quick brown fox."
/// ```
#[violation]
pub struct SingleLineImplicitStringConcatenation;
impl Violation for SingleLineImplicitStringConcatenation {
#[derive_message_formats]
fn message(&self) -> String {
@ -40,42 +40,42 @@ impl Violation for SingleLineImplicitStringConcatenation {
}
}
define_violation!(
/// ## What it does
/// Checks for implicitly concatenated strings that span multiple lines.
///
/// ## Why is this bad?
/// For string literals that wrap across multiple lines, PEP 8 recommends
/// the use of implicit string concatenation within parentheses instead of
/// using a backslash for line continuation, as the former is more readable
/// than the latter.
///
/// By default, this rule will only trigger if the string literal is
/// concatenated via a backslash. To disallow implicit string concatenation
/// altogether, set the `flake8-implicit-str-concat.allow-multiline` option
/// to `false`.
///
/// ## Options
/// - `flake8-implicit-str-concat.allow-multiline`
///
/// ## Example
/// ```python
/// z = "The quick brown fox jumps over the lazy "\
/// "dog."
/// ```
///
/// Use instead:
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// "dog."
/// )
/// ```
///
/// ## References
/// - [PEP 8](https://peps.python.org/pep-0008/#maximum-line-length)
pub struct MultiLineImplicitStringConcatenation;
);
/// ## What it does
/// Checks for implicitly concatenated strings that span multiple lines.
///
/// ## Why is this bad?
/// For string literals that wrap across multiple lines, PEP 8 recommends
/// the use of implicit string concatenation within parentheses instead of
/// using a backslash for line continuation, as the former is more readable
/// than the latter.
///
/// By default, this rule will only trigger if the string literal is
/// concatenated via a backslash. To disallow implicit string concatenation
/// altogether, set the `flake8-implicit-str-concat.allow-multiline` option
/// to `false`.
///
/// ## Options
/// - `flake8-implicit-str-concat.allow-multiline`
///
/// ## Example
/// ```python
/// z = "The quick brown fox jumps over the lazy "\
/// "dog."
/// ```
///
/// Use instead:
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// "dog."
/// )
/// ```
///
/// ## References
/// - [PEP 8](https://peps.python.org/pep-0008/#maximum-line-length)
#[violation]
pub struct MultiLineImplicitStringConcatenation;
impl Violation for MultiLineImplicitStringConcatenation {
#[derive_message_formats]
fn message(&self) -> String {
@ -83,33 +83,33 @@ impl Violation for MultiLineImplicitStringConcatenation {
}
}
define_violation!(
/// ## What it does
/// Checks for string literals that are explicitly concatenated (using the
/// `+` operator).
///
/// ## Why is this bad?
/// For string literals that wrap across multiple lines, implicit string
/// concatenation within parentheses is preferred over explicit
/// concatenation using the `+` operator, as the former is more readable.
///
/// ## Example
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// + "dog"
/// )
/// ```
///
/// Use instead:
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// "dog"
/// )
/// ```
pub struct ExplicitStringConcatenation;
);
/// ## What it does
/// Checks for string literals that are explicitly concatenated (using the
/// `+` operator).
///
/// ## Why is this bad?
/// For string literals that wrap across multiple lines, implicit string
/// concatenation within parentheses is preferred over explicit
/// concatenation using the `+` operator, as the former is more readable.
///
/// ## Example
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// + "dog"
/// )
/// ```
///
/// Use instead:
/// ```python
/// z = (
/// "The quick brown fox jumps over the lazy "
/// "dog"
/// )
/// ```
#[violation]
pub struct ExplicitStringConcatenation;
impl Violation for ExplicitStringConcatenation {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashMap;
use rustpython_parser::ast::Stmt;
@ -6,30 +6,30 @@ use crate::ast::types::Range;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for imports that are typically imported using a common convention,
/// like `import pandas as pd`, and enforces that convention.
///
/// ## Why is this bad?
/// Consistency is good. Use a common convention for imports to make your code
/// more readable and idiomatic.
///
/// For example, `import pandas as pd` is a common
/// convention for importing the `pandas` library, and users typically expect
/// Pandas to be aliased as `pd`.
///
/// ## Example
/// ```python
/// import pandas
/// ```
///
/// Use instead:
/// ```python
/// import pandas as pd
/// ```
pub struct UnconventionalImportAlias(pub String, pub String);
);
/// ## What it does
/// Checks for imports that are typically imported using a common convention,
/// like `import pandas as pd`, and enforces that convention.
///
/// ## Why is this bad?
/// Consistency is good. Use a common convention for imports to make your code
/// more readable and idiomatic.
///
/// For example, `import pandas as pd` is a common
/// convention for importing the `pandas` library, and users typically expect
/// Pandas to be aliased as `pd`.
///
/// ## Example
/// ```python
/// import pandas
/// ```
///
/// Use instead:
/// ```python
/// import pandas as pd
/// ```
#[violation]
pub struct UnconventionalImportAlias(pub String, pub String);
impl Violation for UnconventionalImportAlias {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,10 +1,10 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::violation::{AlwaysAutofixableViolation, Violation};
define_violation!(
pub struct LoggingStringFormat;
);
#[violation]
pub struct LoggingStringFormat;
impl Violation for LoggingStringFormat {
#[derive_message_formats]
fn message(&self) -> String {
@ -12,9 +12,9 @@ impl Violation for LoggingStringFormat {
}
}
define_violation!(
pub struct LoggingPercentFormat;
);
#[violation]
pub struct LoggingPercentFormat;
impl Violation for LoggingPercentFormat {
#[derive_message_formats]
fn message(&self) -> String {
@ -22,9 +22,9 @@ impl Violation for LoggingPercentFormat {
}
}
define_violation!(
pub struct LoggingStringConcat;
);
#[violation]
pub struct LoggingStringConcat;
impl Violation for LoggingStringConcat {
#[derive_message_formats]
fn message(&self) -> String {
@ -32,9 +32,9 @@ impl Violation for LoggingStringConcat {
}
}
define_violation!(
pub struct LoggingFString;
);
#[violation]
pub struct LoggingFString;
impl Violation for LoggingFString {
#[derive_message_formats]
fn message(&self) -> String {
@ -42,9 +42,9 @@ impl Violation for LoggingFString {
}
}
define_violation!(
pub struct LoggingWarn;
);
#[violation]
pub struct LoggingWarn;
impl AlwaysAutofixableViolation for LoggingWarn {
#[derive_message_formats]
fn message(&self) -> String {
@ -56,9 +56,9 @@ impl AlwaysAutofixableViolation for LoggingWarn {
}
}
define_violation!(
pub struct LoggingExtraAttrClash(pub String);
);
#[violation]
pub struct LoggingExtraAttrClash(pub String);
impl Violation for LoggingExtraAttrClash {
#[derive_message_formats]
fn message(&self) -> String {
@ -69,9 +69,9 @@ impl Violation for LoggingExtraAttrClash {
}
}
define_violation!(
pub struct LoggingExcInfo;
);
#[violation]
pub struct LoggingExcInfo;
impl Violation for LoggingExcInfo {
#[derive_message_formats]
fn message(&self) -> String {
@ -79,9 +79,9 @@ impl Violation for LoggingExcInfo {
}
}
define_violation!(
pub struct LoggingRedundantExcInfo;
);
#[violation]
pub struct LoggingRedundantExcInfo;
impl Violation for LoggingRedundantExcInfo {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,35 +1,35 @@
use std::path::{Path, PathBuf};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::fs;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Checks for packages that are missing an `__init__.py` file.
///
/// ## Why is this bad?
/// Python packages are directories that contain a file named `__init__.py`.
/// The existence of this file indicates that the directory is a Python
/// package, and so it can be imported the same way a module can be
/// imported.
///
/// Directories that lack an `__init__.py` file can still be imported, but
/// they're indicative of a special kind of package, known as a "namespace
/// package" (see: [PEP 420](https://www.python.org/dev/peps/pep-0420/)).
/// Namespace packages are less widely used, so a package that lacks an
/// `__init__.py` file is typically meant to be a regular package, and
/// the absence of the `__init__.py` file is probably an oversight.
///
/// ## Options
/// - `namespace-packages`
pub struct ImplicitNamespacePackage {
pub filename: String,
}
);
/// ## What it does
/// Checks for packages that are missing an `__init__.py` file.
///
/// ## Why is this bad?
/// Python packages are directories that contain a file named `__init__.py`.
/// The existence of this file indicates that the directory is a Python
/// package, and so it can be imported the same way a module can be
/// imported.
///
/// Directories that lack an `__init__.py` file can still be imported, but
/// they're indicative of a special kind of package, known as a "namespace
/// package" (see: [PEP 420](https://www.python.org/dev/peps/pep-0420/)).
/// Namespace packages are less widely used, so a package that lacks an
/// `__init__.py` file is typically meant to be a regular package, and
/// the absence of the `__init__.py` file is probably an oversight.
///
/// ## Options
/// - `namespace-packages`
#[violation]
pub struct ImplicitNamespacePackage {
pub filename: String,
}
impl Violation for ImplicitNamespacePackage {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use log::error;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use ruff_python::identifiers::is_identifier;
use ruff_python::keyword::KWLIST;
use rustc_hash::FxHashSet;
@ -17,9 +17,9 @@ use crate::violation::{AlwaysAutofixableViolation, Violation};
use super::fixes;
define_violation!(
pub struct UnnecessaryPass;
);
#[violation]
pub struct UnnecessaryPass;
impl AlwaysAutofixableViolation for UnnecessaryPass {
#[derive_message_formats]
fn message(&self) -> String {
@ -31,9 +31,9 @@ impl AlwaysAutofixableViolation for UnnecessaryPass {
}
}
define_violation!(
pub struct DupeClassFieldDefinitions(pub String);
);
#[violation]
pub struct DupeClassFieldDefinitions(pub String);
impl AlwaysAutofixableViolation for DupeClassFieldDefinitions {
#[derive_message_formats]
fn message(&self) -> String {
@ -47,11 +47,11 @@ impl AlwaysAutofixableViolation for DupeClassFieldDefinitions {
}
}
define_violation!(
pub struct PreferUniqueEnums {
pub value: String,
}
);
#[violation]
pub struct PreferUniqueEnums {
pub value: String,
}
impl Violation for PreferUniqueEnums {
#[derive_message_formats]
fn message(&self) -> String {
@ -60,39 +60,39 @@ impl Violation for PreferUniqueEnums {
}
}
define_violation!(
/// ## What it does
/// Checks for unnecessary list comprehensions passed to `any` and `all`.
///
/// ## Why is this bad?
/// `any` and `all` take any iterators, including generators. Converting a generator to a list
/// by way of a list comprehension is unnecessary and reduces performance due to the
/// overhead of creating the list.
///
/// For example, compare the performance of `all` with a list comprehension against that
/// of a generator (~40x faster here):
///
/// ```console
/// In [1]: %timeit all([i for i in range(1000)])
/// 8.14 µs ± 25.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
///
/// In [2]: %timeit all(i for i in range(1000))
/// 212 ns ± 0.892 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
/// ```
///
/// ## Examples
/// ```python
/// any([x.id for x in bar])
/// all([x.id for x in bar])
/// ```
///
/// Use instead:
/// ```python
/// any(x.id for x in bar)
/// all(x.id for x in bar)
/// ```
pub struct UnnecessaryComprehensionAnyAll;
);
/// ## What it does
/// Checks for unnecessary list comprehensions passed to `any` and `all`.
///
/// ## Why is this bad?
/// `any` and `all` take any iterators, including generators. Converting a generator to a list
/// by way of a list comprehension is unnecessary and reduces performance due to the
/// overhead of creating the list.
///
/// For example, compare the performance of `all` with a list comprehension against that
/// of a generator (~40x faster here):
///
/// ```console
/// In [1]: %timeit all([i for i in range(1000)])
/// 8.14 µs ± 25.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
///
/// In [2]: %timeit all(i for i in range(1000))
/// 212 ns ± 0.892 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
/// ```
///
/// ## Examples
/// ```python
/// any([x.id for x in bar])
/// all([x.id for x in bar])
/// ```
///
/// Use instead:
/// ```python
/// any(x.id for x in bar)
/// all(x.id for x in bar)
/// ```
#[violation]
pub struct UnnecessaryComprehensionAnyAll;
impl AlwaysAutofixableViolation for UnnecessaryComprehensionAnyAll {
#[derive_message_formats]
fn message(&self) -> String {
@ -104,9 +104,9 @@ impl AlwaysAutofixableViolation for UnnecessaryComprehensionAnyAll {
}
}
define_violation!(
pub struct UnnecessarySpread;
);
#[violation]
pub struct UnnecessarySpread;
impl Violation for UnnecessarySpread {
#[derive_message_formats]
fn message(&self) -> String {
@ -114,11 +114,11 @@ impl Violation for UnnecessarySpread {
}
}
define_violation!(
pub struct SingleStartsEndsWith {
pub attr: String,
}
);
#[violation]
pub struct SingleStartsEndsWith {
pub attr: String,
}
impl Violation for SingleStartsEndsWith {
#[derive_message_formats]
fn message(&self) -> String {
@ -127,9 +127,9 @@ impl Violation for SingleStartsEndsWith {
}
}
define_violation!(
pub struct UnnecessaryDictKwargs;
);
#[violation]
pub struct UnnecessaryDictKwargs;
impl Violation for UnnecessaryDictKwargs {
#[derive_message_formats]
fn message(&self) -> String {
@ -137,9 +137,9 @@ impl Violation for UnnecessaryDictKwargs {
}
}
define_violation!(
pub struct PreferListBuiltin;
);
#[violation]
pub struct PreferListBuiltin;
impl AlwaysAutofixableViolation for PreferListBuiltin {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Expr, Keyword};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::helpers::is_const_none;
use crate::ast::types::Range;
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct PrintFound;
);
#[violation]
pub struct PrintFound;
impl Violation for PrintFound {
#[derive_message_formats]
fn message(&self) -> String {
@ -18,9 +18,9 @@ impl Violation for PrintFound {
}
}
define_violation!(
pub struct PPrintFound;
);
#[violation]
pub struct PPrintFound;
impl Violation for PPrintFound {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,56 +1,56 @@
use rustpython_parser::ast::{Cmpop, Expr};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
use crate::Range;
define_violation!(
/// ## What it does
/// Checks for usages of comparators other than `<` and `>=` for
/// `sys.version_info` checks in `.pyi` files. All other comparators, such
/// as `>`, `<=`, and `==`, are banned.
///
/// ## Why is this bad?
/// Comparing `sys.version_info` with `==` or `<=` has unexpected behavior
/// and can lead to bugs.
///
/// For example, `sys.version_info > (3, 8)` will also match `3.8.10`,
/// while `sys.version_info <= (3, 8)` will _not_ match `3.8.10`:
///
/// ```python
/// >>> import sys
/// >>> print(sys.version_info)
/// sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)
/// >>> print(sys.version_info > (3, 8))
/// True
/// >>> print(sys.version_info == (3, 8))
/// False
/// >>> print(sys.version_info <= (3, 8))
/// False
/// >>> print(sys.version_info in (3, 8))
/// False
/// ```
///
/// ## Example
/// ```python
/// import sys
///
/// if sys.version_info > (3, 8):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// import sys
///
/// if sys.version_info >= (3, 9):
/// ...
/// ```
pub struct BadVersionInfoComparison;
);
/// ## What it does
/// Checks for usages of comparators other than `<` and `>=` for
/// `sys.version_info` checks in `.pyi` files. All other comparators, such
/// as `>`, `<=`, and `==`, are banned.
///
/// ## Why is this bad?
/// Comparing `sys.version_info` with `==` or `<=` has unexpected behavior
/// and can lead to bugs.
///
/// For example, `sys.version_info > (3, 8)` will also match `3.8.10`,
/// while `sys.version_info <= (3, 8)` will _not_ match `3.8.10`:
///
/// ```python
/// >>> import sys
/// >>> print(sys.version_info)
/// sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)
/// >>> print(sys.version_info > (3, 8))
/// True
/// >>> print(sys.version_info == (3, 8))
/// False
/// >>> print(sys.version_info <= (3, 8))
/// False
/// >>> print(sys.version_info in (3, 8))
/// False
/// ```
///
/// ## Example
/// ```python
/// import sys
///
/// if sys.version_info > (3, 8):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// import sys
///
/// if sys.version_info >= (3, 9):
/// ...
/// ```
#[violation]
pub struct BadVersionInfoComparison;
impl Violation for BadVersionInfoComparison {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,15 +1,15 @@
use rustpython_parser::ast::Expr;
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct DocstringInStub;
);
#[violation]
pub struct DocstringInStub;
impl Violation for DocstringInStub {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,15 +1,15 @@
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct NonEmptyStubBody;
);
#[violation]
pub struct NonEmptyStubBody;
impl Violation for NonEmptyStubBody {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,15 +1,15 @@
use rustpython_parser::ast::{Stmt, StmtKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct PassStatementStubBody;
);
#[violation]
pub struct PassStatementStubBody;
impl Violation for PassStatementStubBody {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, ExprKind};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -25,32 +25,32 @@ impl fmt::Display for VarKind {
}
}
define_violation!(
/// ## What it does
/// Checks that type `TypeVar`, `ParamSpec`, and `TypeVarTuple` definitions in
/// stubs are prefixed with `_`.
///
/// ## Why is this bad?
/// By prefixing type parameters with `_`, we can avoid accidentally exposing
/// names internal to the stub.
///
/// ## Example
/// ```python
/// from typing import TypeVar
///
/// T = TypeVar("T")
/// ```
///
/// Use instead:
/// ```python
/// from typing import TypeVar
///
/// _T = TypeVar("_T")
/// ```
pub struct PrefixTypeParams {
pub kind: VarKind,
}
);
/// ## What it does
/// Checks that type `TypeVar`, `ParamSpec`, and `TypeVarTuple` definitions in
/// stubs are prefixed with `_`.
///
/// ## Why is this bad?
/// By prefixing type parameters with `_`, we can avoid accidentally exposing
/// names internal to the stub.
///
/// ## Example
/// ```python
/// from typing import TypeVar
///
/// T = TypeVar("T")
/// ```
///
/// Use instead:
/// ```python
/// from typing import TypeVar
///
/// _T = TypeVar("_T")
/// ```
#[violation]
pub struct PrefixTypeParams {
pub kind: VarKind,
}
impl Violation for PrefixTypeParams {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -1,15 +1,15 @@
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind, Operator, Unaryop};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct TypedArgumentSimpleDefaults;
);
#[violation]
pub struct TypedArgumentSimpleDefaults;
/// PYI011
impl Violation for TypedArgumentSimpleDefaults {
#[derive_message_formats]
@ -18,9 +18,9 @@ impl Violation for TypedArgumentSimpleDefaults {
}
}
define_violation!(
pub struct ArgumentSimpleDefaults;
);
#[violation]
pub struct ArgumentSimpleDefaults;
/// PYI014
impl Violation for ArgumentSimpleDefaults {
#[derive_message_formats]

View file

@ -1,48 +1,48 @@
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation;
define_violation!(
/// ## What it does
/// Check for unrecognized `sys.platform` checks. Platform checks should be
/// simple string comparisons.
///
/// **Note**: this rule is only enabled in `.pyi` stub files.
///
/// ## Why is this bad?
/// Some `sys.platform` checks are too complex for type checkers to
/// understand, and thus result in false positives. `sys.platform` checks
/// should be simple string comparisons, like `sys.platform == "linux"`.
///
/// ## Example
/// ```python
/// if sys.platform.startswith("linux"):
/// # Linux specific definitions
/// ...
/// else:
/// # Posix specific definitions
/// ...
/// ```
///
/// Instead, use a simple string comparison, such as `==` or `!=`:
/// ```python
/// if sys.platform == "linux":
/// # Linux specific definitions
/// ...
/// else:
/// # Posix specific definitions
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
pub struct UnrecognizedPlatformCheck;
);
/// ## What it does
/// Check for unrecognized `sys.platform` checks. Platform checks should be
/// simple string comparisons.
///
/// **Note**: this rule is only enabled in `.pyi` stub files.
///
/// ## Why is this bad?
/// Some `sys.platform` checks are too complex for type checkers to
/// understand, and thus result in false positives. `sys.platform` checks
/// should be simple string comparisons, like `sys.platform == "linux"`.
///
/// ## Example
/// ```python
/// if sys.platform.startswith("linux"):
/// # Linux specific definitions
/// ...
/// else:
/// # Posix specific definitions
/// ...
/// ```
///
/// Instead, use a simple string comparison, such as `==` or `!=`:
/// ```python
/// if sys.platform == "linux":
/// # Linux specific definitions
/// ...
/// else:
/// # Posix specific definitions
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
#[violation]
pub struct UnrecognizedPlatformCheck;
impl Violation for UnrecognizedPlatformCheck {
#[derive_message_formats]
fn message(&self) -> String {
@ -50,37 +50,37 @@ impl Violation for UnrecognizedPlatformCheck {
}
}
define_violation!(
/// ## What it does
/// Check for unrecognized platform names in `sys.platform` checks.
///
/// **Note**: this rule is only enabled in `.pyi` stub files.
///
/// ## Why is this bad?
/// If a `sys.platform` check compares to a platform name outside of a
/// small set of known platforms (e.g. "linux", "win32", etc.), it's likely
/// a typo or a platform name that is not recognized by type checkers.
///
/// The list of known platforms is: "linux", "win32", "cygwin", "darwin".
///
/// ## Example
/// ```python
/// if sys.platform == "linus":
/// ...
/// ```
///
/// Use instead:
/// ```python
/// if sys.platform == "linux":
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
pub struct UnrecognizedPlatformName {
pub platform: String,
}
);
/// ## What it does
/// Check for unrecognized platform names in `sys.platform` checks.
///
/// **Note**: this rule is only enabled in `.pyi` stub files.
///
/// ## Why is this bad?
/// If a `sys.platform` check compares to a platform name outside of a
/// small set of known platforms (e.g. "linux", "win32", etc.), it's likely
/// a typo or a platform name that is not recognized by type checkers.
///
/// The list of known platforms is: "linux", "win32", "cygwin", "darwin".
///
/// ## Example
/// ```python
/// if sys.platform == "linus":
/// ...
/// ```
///
/// Use instead:
/// ```python
/// if sys.platform == "linux":
/// ...
/// ```
///
/// ## References
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
#[violation]
pub struct UnrecognizedPlatformName {
pub platform: String,
}
impl Violation for UnrecognizedPlatformName {
#[derive_message_formats]
fn message(&self) -> String {

View file

@ -10,7 +10,7 @@ use rustpython_parser::ast::{
Unaryop,
};
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use crate::ast::helpers::{has_comments_in, unparse_stmt};
use crate::ast::types::Range;
@ -26,39 +26,39 @@ use crate::violation::{AutofixKind, Availability, Violation};
use super::helpers::is_falsy_constant;
use super::unittest_assert::UnittestAssert;
define_violation!(
/// ## What it does
/// Checks for assertions that combine multiple independent conditions.
///
/// ## Why is this bad?
/// Composite assertion statements are harder debug upon failure, as the
/// failure message will not indicate which condition failed.
///
/// ## Example
/// ```python
/// def test_foo():
/// assert something and something_else
///
///
/// def test_bar():
/// assert not (something or something_else)
/// ```
///
/// Use instead:
/// ```python
/// def test_foo():
/// assert something
/// assert something_else
///
///
/// def test_bar():
/// assert not something
/// assert not something_else
/// ```
pub struct CompositeAssertion {
pub fixable: bool,
}
);
/// ## What it does
/// Checks for assertions that combine multiple independent conditions.
///
/// ## Why is this bad?
/// Composite assertion statements are harder debug upon failure, as the
/// failure message will not indicate which condition failed.
///
/// ## Example
/// ```python
/// def test_foo():
/// assert something and something_else
///
///
/// def test_bar():
/// assert not (something or something_else)
/// ```
///
/// Use instead:
/// ```python
/// def test_foo():
/// assert something
/// assert something_else
///
///
/// def test_bar():
/// assert not something
/// assert not something_else
/// ```
#[violation]
pub struct CompositeAssertion {
pub fixable: bool,
}
impl Violation for CompositeAssertion {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));
@ -73,11 +73,11 @@ impl Violation for CompositeAssertion {
}
}
define_violation!(
pub struct AssertInExcept {
pub name: String,
}
);
#[violation]
pub struct AssertInExcept {
pub name: String,
}
impl Violation for AssertInExcept {
#[derive_message_formats]
fn message(&self) -> String {
@ -88,9 +88,9 @@ impl Violation for AssertInExcept {
}
}
define_violation!(
pub struct AssertAlwaysFalse;
);
#[violation]
pub struct AssertAlwaysFalse;
impl Violation for AssertAlwaysFalse {
#[derive_message_formats]
fn message(&self) -> String {
@ -98,12 +98,12 @@ impl Violation for AssertAlwaysFalse {
}
}
define_violation!(
pub struct UnittestAssertion {
pub assertion: String,
pub fixable: bool,
}
);
#[violation]
pub struct UnittestAssertion {
pub assertion: String,
pub fixable: bool,
}
impl Violation for UnittestAssertion {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));

View file

@ -1,4 +1,4 @@
use ruff_macros::{define_violation, derive_message_formats};
use ruff_macros::{derive_message_formats, violation};
use rustpython_parser::ast::{Expr, Keyword};
use super::helpers::{is_empty_or_null_string, is_pytest_fail};
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct FailWithoutMessage;
);
#[violation]
pub struct FailWithoutMessage;
impl Violation for FailWithoutMessage {
#[derive_message_formats]
fn message(&self) -> String {

Some files were not shown because too many files have changed in this diff Show more