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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Excepthandler, Expr, Stmt, StmtKind}; 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::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -8,9 +8,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_bandit::helpers::is_untyped_exception; use crate::rules::flake8_bandit::helpers::is_untyped_exception;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct TryExceptPass; pub struct TryExceptPass;
);
impl Violation for TryExceptPass { impl Violation for TryExceptPass {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind, Keyword};
use crate::ast::helpers::SimpleCallArgs; use crate::ast::helpers::SimpleCallArgs;
@ -7,11 +7,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct UnsafeYAMLLoad { pub struct UnsafeYAMLLoad {
pub loader: Option<String>, pub loader: Option<String>,
} }
);
impl Violation for UnsafeYAMLLoad { impl Violation for UnsafeYAMLLoad {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use crate::ast::helpers; use crate::ast::helpers;
@ -8,11 +8,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct BlindExcept { pub struct BlindExcept {
pub name: String, pub name: String,
} }
);
impl Violation for BlindExcept { impl Violation for BlindExcept {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind}; 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::helpers::collect_call_path;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, DiagnosticKind}; use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct BooleanPositionalArgInFunctionDefinition; pub struct BooleanPositionalArgInFunctionDefinition;
);
impl Violation for BooleanPositionalArgInFunctionDefinition { impl Violation for BooleanPositionalArgInFunctionDefinition {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -18,9 +18,9 @@ impl Violation for BooleanPositionalArgInFunctionDefinition {
} }
} }
define_violation!( #[violation]
pub struct BooleanDefaultValueInFunctionDefinition; pub struct BooleanDefaultValueInFunctionDefinition;
);
impl Violation for BooleanDefaultValueInFunctionDefinition { impl Violation for BooleanDefaultValueInFunctionDefinition {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -28,9 +28,9 @@ impl Violation for BooleanDefaultValueInFunctionDefinition {
} }
} }
define_violation!( #[violation]
pub struct BooleanPositionalValueInFunctionCall; pub struct BooleanPositionalValueInFunctionCall;
);
impl Violation for BooleanPositionalValueInFunctionCall { impl Violation for BooleanPositionalValueInFunctionCall {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -7,11 +7,11 @@ use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation; use crate::violation::Violation;
use crate::visibility::{is_abstract, is_overload}; use crate::visibility::{is_abstract, is_overload};
define_violation!( #[violation]
pub struct AbstractBaseClassWithoutAbstractMethod { pub struct AbstractBaseClassWithoutAbstractMethod {
pub name: String, pub name: String,
} }
);
impl Violation for AbstractBaseClassWithoutAbstractMethod { impl Violation for AbstractBaseClassWithoutAbstractMethod {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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") format!("`{name}` is an abstract base class, but it has no abstract methods")
} }
} }
define_violation!( #[violation]
pub struct EmptyMethodWithoutAbstractDecorator { pub struct EmptyMethodWithoutAbstractDecorator {
pub name: String, pub name: String,
} }
);
impl Violation for EmptyMethodWithoutAbstractDecorator { impl Violation for EmptyMethodWithoutAbstractDecorator {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
use crate::ast::helpers::unparse_stmt; use crate::ast::helpers::unparse_stmt;
@ -8,9 +8,9 @@ use crate::fix::Fix;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation; use crate::violation::AlwaysAutofixableViolation;
define_violation!( #[violation]
pub struct AssertFalse; pub struct AssertFalse;
);
impl AlwaysAutofixableViolation for AssertFalse { impl AlwaysAutofixableViolation for AssertFalse {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{ExprKind, Stmt, Withitem};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,28 +6,28 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( /// ## What it does
/// ## What it does /// Checks for `self.assertRaises(Exception)`.
/// Checks for `self.assertRaises(Exception)`. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// `assertRaises(Exception)` can lead to your test passing even if the
/// `assertRaises(Exception)` can lead to your test passing even if the /// code being tested is never executed due to a typo.
/// code being tested is never executed due to a typo. ///
/// /// Either assert for a more specific exception (builtin or custom), use
/// Either assert for a more specific exception (builtin or custom), use /// `assertRaisesRegex` or the context manager form of `assertRaises`.
/// `assertRaisesRegex` or the context manager form of `assertRaises`. ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// self.assertRaises(Exception, foo)
/// self.assertRaises(Exception, foo) /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// self.assertRaises(SomeSpecificException, foo)
/// self.assertRaises(SomeSpecificException, foo) /// ```
/// ``` #[violation]
pub struct AssertRaisesException; pub struct AssertRaisesException;
);
impl Violation for AssertRaisesException { impl Violation for AssertRaisesException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct AssignmentToOsEnviron; pub struct AssignmentToOsEnviron;
);
impl Violation for AssignmentToOsEnviron { impl Violation for AssignmentToOsEnviron {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::{Range, ScopeKind}; use crate::ast::types::{Range, ScopeKind};
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct CachedInstanceMethod; pub struct CachedInstanceMethod;
);
impl Violation for CachedInstanceMethod { impl Violation for CachedInstanceMethod {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct CannotRaiseLiteral; pub struct CannotRaiseLiteral;
);
impl Violation for CannotRaiseLiteral { impl Violation for CannotRaiseLiteral {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools; use itertools::Itertools;
use ruff_macros::{define_violation, derive_message_formats}; use ruff_macros::{derive_message_formats, violation};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location,
@ -13,11 +13,11 @@ use crate::fix::Fix;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::violation::{AlwaysAutofixableViolation, Violation}; use crate::violation::{AlwaysAutofixableViolation, Violation};
define_violation!( #[violation]
pub struct DuplicateTryBlockException { pub struct DuplicateTryBlockException {
pub name: String, pub name: String,
} }
);
impl Violation for DuplicateTryBlockException { impl Violation for DuplicateTryBlockException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -25,11 +25,11 @@ impl Violation for DuplicateTryBlockException {
format!("try-except block with duplicate exception `{name}`") format!("try-except block with duplicate exception `{name}`")
} }
} }
define_violation!( #[violation]
pub struct DuplicateHandlerException { pub struct DuplicateHandlerException {
pub names: Vec<String>, pub names: Vec<String>,
} }
);
impl AlwaysAutofixableViolation for DuplicateHandlerException { impl AlwaysAutofixableViolation for DuplicateHandlerException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::Excepthandler;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -8,9 +8,9 @@ use crate::violation::Violation;
use rustpython_parser::ast::{ExcepthandlerKind, ExprKind}; use rustpython_parser::ast::{ExcepthandlerKind, ExprKind};
define_violation!( #[violation]
pub struct ExceptWithEmptyTuple; pub struct ExceptWithEmptyTuple;
);
impl Violation for ExceptWithEmptyTuple { impl Violation for ExceptWithEmptyTuple {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
use crate::ast::helpers; use crate::ast::helpers;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct FStringDocstring; pub struct FStringDocstring;
);
impl Violation for FStringDocstring { impl Violation for FStringDocstring {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
use super::mutable_argument_default::is_mutable_func; use super::mutable_argument_default::is_mutable_func;
@ -10,11 +10,11 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, DiagnosticKind}; use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct FunctionCallArgumentDefault { pub struct FunctionCallArgumentDefault {
pub name: Option<String>, pub name: Option<String>,
} }
);
impl Violation for FunctionCallArgumentDefault { impl Violation for FunctionCallArgumentDefault {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustc_hash::FxHashSet;
use rustpython_parser::ast::{Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind}; 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::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct FunctionUsesLoopVariable { pub struct FunctionUsesLoopVariable {
pub name: String, pub name: String,
} }
);
impl Violation for FunctionUsesLoopVariable { impl Violation for FunctionUsesLoopVariable {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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::identifiers::{is_identifier, is_mangled_private};
use ruff_python::keyword::KWLIST; use ruff_python::keyword::KWLIST;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location}; use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location};
@ -10,9 +10,9 @@ use crate::fix::Fix;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation; use crate::violation::AlwaysAutofixableViolation;
define_violation!( #[violation]
pub struct GetAttrWithConstant; pub struct GetAttrWithConstant;
);
impl AlwaysAutofixableViolation for GetAttrWithConstant { impl AlwaysAutofixableViolation for GetAttrWithConstant {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Stmt, StmtKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,11 +6,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct JumpStatementInFinally { pub struct JumpStatementInFinally {
pub name: String, pub name: String,
} }
);
impl Violation for JumpStatementInFinally { impl Violation for JumpStatementInFinally {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind}; use rustpython_parser::ast::{Expr, ExprKind};
@ -9,11 +9,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct LoopVariableOverridesIterator { pub struct LoopVariableOverridesIterator {
pub name: String, pub name: String,
} }
);
impl Violation for LoopVariableOverridesIterator { impl Violation for LoopVariableOverridesIterator {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind, Operator};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct MutableArgumentDefault; pub struct MutableArgumentDefault;
);
impl Violation for MutableArgumentDefault { impl Violation for MutableArgumentDefault {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -1,6 +1,6 @@
use rustpython_parser::ast::{ExprKind, Stmt}; 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 ruff_python::str::is_lower;
use crate::ast::helpers::RaiseStatementVisitor; use crate::ast::helpers::RaiseStatementVisitor;
@ -9,9 +9,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct RaiseWithoutFromInsideExcept; pub struct RaiseWithoutFromInsideExcept;
);
impl Violation for RaiseWithoutFromInsideExcept { impl Violation for RaiseWithoutFromInsideExcept {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, ExprKind};
use crate::ast::helpers::unparse_expr; use crate::ast::helpers::unparse_expr;
@ -8,11 +8,11 @@ use crate::fix::Fix;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation; use crate::violation::AlwaysAutofixableViolation;
define_violation!( #[violation]
pub struct RedundantTupleInExceptionHandler { pub struct RedundantTupleInExceptionHandler {
pub name: String, pub name: String,
} }
);
impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler { impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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::identifiers::{is_identifier, is_mangled_private};
use ruff_python::keyword::KWLIST; use ruff_python::keyword::KWLIST;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind}; 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::source_code::Stylist;
use crate::violation::AlwaysAutofixableViolation; use crate::violation::AlwaysAutofixableViolation;
define_violation!( #[violation]
pub struct SetAttrWithConstant; pub struct SetAttrWithConstant;
);
impl AlwaysAutofixableViolation for SetAttrWithConstant { impl AlwaysAutofixableViolation for SetAttrWithConstant {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

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

View file

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

View file

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

View file

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

View file

@ -18,7 +18,7 @@
//! method() //! method()
//! ``` //! ```
use ruff_macros::{define_violation, derive_message_formats}; use ruff_macros::{derive_message_formats, violation};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind, Stmt}; use rustpython_parser::ast::{Expr, ExprKind, Stmt};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -37,20 +37,20 @@ pub enum Certainty {
Uncertain, Uncertain,
} }
define_violation!( #[violation]
pub struct UnusedLoopControlVariable { pub struct UnusedLoopControlVariable {
/// The name of the loop control variable. /// The name of the loop control variable.
pub name: String, pub name: String,
/// The name to which the variable should be renamed, if it can be /// The name to which the variable should be renamed, if it can be
/// safely renamed. /// safely renamed.
pub rename: Option<String>, pub rename: Option<String>,
/// Whether the variable is certain to be unused in the loop body, or /// Whether the variable is certain to be unused in the loop body, or
/// merely suspect. A variable _may_ be used, but undetectably /// merely suspect. A variable _may_ be used, but undetectably
/// so, if the loop incorporates by magic control flow (e.g., /// so, if the loop incorporates by magic control flow (e.g.,
/// `locals()`). /// `locals()`).
pub certainty: Certainty, pub certainty: Certainty,
} }
);
impl Violation for UnusedLoopControlVariable { impl Violation for UnusedLoopControlVariable {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes)); 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 rustpython_parser::ast::{Expr, ExprKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct UselessComparison; pub struct UselessComparison;
);
impl Violation for UselessComparison { impl Violation for UselessComparison {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::Expr;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct UselessContextlibSuppress; pub struct UselessContextlibSuppress;
);
impl Violation for UselessContextlibSuppress { impl Violation for UselessContextlibSuppress {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct UselessExpression; pub struct UselessExpression;
);
impl Violation for UselessExpression { impl Violation for UselessExpression {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, ExprKind, Keyword};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct ZipWithoutExplicitStrict; pub struct ZipWithoutExplicitStrict;
);
impl Violation for ZipWithoutExplicitStrict { impl Violation for ZipWithoutExplicitStrict {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 ruff_python::builtins::BUILTINS;
use rustpython_parser::ast::Located; use rustpython_parser::ast::Located;
@ -7,49 +7,49 @@ use crate::ast::types::Range;
use crate::registry::{Diagnostic, DiagnosticKind}; use crate::registry::{Diagnostic, DiagnosticKind};
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( /// ## What it does
/// ## What it does /// Checks for variable (and function) assignments that use the same name
/// Checks for variable (and function) assignments that use the same name /// as a builtin.
/// as a builtin. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Reusing a builtin name for the name of a variable increases the
/// Reusing a builtin name for the name of a variable increases the /// difficulty of reading and maintaining the code, and can cause
/// difficulty of reading and maintaining the code, and can cause /// non-obvious errors, as readers may mistake the variable for the
/// non-obvious errors, as readers may mistake the variable for the /// builtin and vice versa.
/// builtin and vice versa. ///
/// /// Builtins can be marked as exceptions to this rule via the
/// Builtins can be marked as exceptions to this rule via the /// [`flake8-builtins.builtins-ignorelist`] configuration option.
/// [`flake8-builtins.builtins-ignorelist`] configuration option. ///
/// /// ## Options
/// ## Options ///
/// /// - `flake8-builtins.builtins-ignorelist`
/// - `flake8-builtins.builtins-ignorelist` ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// def find_max(list_of_lists):
/// def find_max(list_of_lists): /// max = 0
/// max = 0 /// for flat_list in list_of_lists:
/// for flat_list in list_of_lists: /// for value in flat_list:
/// for value in flat_list: /// max = max(max, value) # TypeError: 'int' object is not callable
/// max = max(max, value) # TypeError: 'int' object is not callable /// return max
/// return max /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// def find_max(list_of_lists):
/// def find_max(list_of_lists): /// result = 0
/// result = 0 /// for flat_list in list_of_lists:
/// for flat_list in list_of_lists: /// for value in flat_list:
/// for value in flat_list: /// result = max(result, value)
/// result = max(result, value) /// return result
/// 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)
/// - [_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 struct BuiltinVariableShadowing {
pub name: String, pub name: String,
} }
);
impl Violation for BuiltinVariableShadowing { impl Violation for BuiltinVariableShadowing {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -58,52 +58,52 @@ impl Violation for BuiltinVariableShadowing {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for any function arguments that use the same name as a builtin.
/// Checks for any function arguments that use the same name as a builtin. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Reusing a builtin name for the name of an argument increases the
/// Reusing a builtin name for the name of an argument increases the /// difficulty of reading and maintaining the code, and can cause
/// difficulty of reading and maintaining the code, and can cause /// non-obvious errors, as readers may mistake the argument for the
/// non-obvious errors, as readers may mistake the argument for the /// builtin and vice versa.
/// builtin and vice versa. ///
/// /// Builtins can be marked as exceptions to this rule via the
/// Builtins can be marked as exceptions to this rule via the /// [`flake8-builtins.builtins-ignorelist`] configuration option.
/// [`flake8-builtins.builtins-ignorelist`] configuration option. ///
/// /// ## Options
/// ## Options ///
/// /// - `flake8-builtins.builtins-ignorelist`
/// - `flake8-builtins.builtins-ignorelist` ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// def remove_duplicates(list, list2):
/// def remove_duplicates(list, list2): /// result = set()
/// result = set() /// for value in list:
/// for value in list: /// result.add(value)
/// result.add(value) /// for value in list2:
/// for value in list2: /// result.add(value)
/// result.add(value) /// return list(result) # TypeError: 'list' object is not callable
/// return list(result) # TypeError: 'list' object is not callable /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// def remove_duplicates(list1, list2):
/// def remove_duplicates(list1, list2): /// result = set()
/// result = set() /// for value in list1:
/// for value in list1: /// result.add(value)
/// result.add(value) /// for value in list2:
/// for value in list2: /// result.add(value)
/// result.add(value) /// return list(result)
/// return list(result) /// ```
/// ``` ///
/// /// ## References
/// ## 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)
/// - [_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)
/// - [_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 struct BuiltinArgumentShadowing {
pub name: String, pub name: String,
} }
);
impl Violation for BuiltinArgumentShadowing { impl Violation for BuiltinArgumentShadowing {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -112,53 +112,53 @@ impl Violation for BuiltinArgumentShadowing {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for any class attributes that use the same name as a builtin.
/// Checks for any class attributes that use the same name as a builtin. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Reusing a builtin name for the name of an attribute increases the
/// Reusing a builtin name for the name of an attribute increases the /// difficulty of reading and maintaining the code, and can cause
/// difficulty of reading and maintaining the code, and can cause /// non-obvious errors, as readers may mistake the attribute for the
/// non-obvious errors, as readers may mistake the attribute for the /// builtin and vice versa.
/// builtin and vice versa. ///
/// /// Builtins can be marked as exceptions to this rule via the
/// Builtins can be marked as exceptions to this rule via the /// [`flake8-builtins.builtins-ignorelist`] configuration option, or
/// [`flake8-builtins.builtins-ignorelist`] configuration option, or /// converted to the appropriate dunder method.
/// converted to the appropriate dunder method. ///
/// /// ## Options
/// ## Options ///
/// /// - `flake8-builtins.builtins-ignorelist`
/// - `flake8-builtins.builtins-ignorelist` ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// class Shadow:
/// class Shadow: /// def int():
/// def int(): /// return 0
/// return 0 /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// class Shadow:
/// class Shadow: /// def to_int():
/// def to_int(): /// return 0
/// return 0 /// ```
/// ``` ///
/// /// Or:
/// Or: /// ```python
/// ```python /// class Shadow:
/// class Shadow: /// # Callable as `int(shadow)`
/// # Callable as `int(shadow)` /// def __int__():
/// def __int__(): /// return 0
/// return 0 /// ```
/// ``` ///
/// /// ## References
/// ## 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)
/// - [_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)
/// - [_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 struct BuiltinAttributeShadowing {
pub name: String, pub name: String,
} }
);
impl Violation for BuiltinAttributeShadowing { impl Violation for BuiltinAttributeShadowing {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt; 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 rustpython_parser::ast::{Constant, Expr, ExprKind, Unaryop};
use super::helpers; use super::helpers;
@ -8,11 +8,11 @@ use crate::checkers::ast::Checker;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct UnnecessarySubscriptReversal { pub struct UnnecessarySubscriptReversal {
pub func: String, pub func: String,
} }
);
impl Violation for UnnecessarySubscriptReversal { impl Violation for UnnecessarySubscriptReversal {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use crate::ast::helpers::{has_non_none_keyword, is_const_none}; 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::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct CallDatetimeWithoutTzinfo; pub struct CallDatetimeWithoutTzinfo;
);
impl Violation for CallDatetimeWithoutTzinfo { impl Violation for CallDatetimeWithoutTzinfo {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -17,9 +17,9 @@ impl Violation for CallDatetimeWithoutTzinfo {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeToday; pub struct CallDatetimeToday;
);
impl Violation for CallDatetimeToday { impl Violation for CallDatetimeToday {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -30,9 +30,9 @@ impl Violation for CallDatetimeToday {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeUtcnow; pub struct CallDatetimeUtcnow;
);
impl Violation for CallDatetimeUtcnow { impl Violation for CallDatetimeUtcnow {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -43,9 +43,9 @@ impl Violation for CallDatetimeUtcnow {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeUtcfromtimestamp; pub struct CallDatetimeUtcfromtimestamp;
);
impl Violation for CallDatetimeUtcfromtimestamp { impl Violation for CallDatetimeUtcfromtimestamp {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -56,9 +56,9 @@ impl Violation for CallDatetimeUtcfromtimestamp {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeNowWithoutTzinfo; pub struct CallDatetimeNowWithoutTzinfo;
);
impl Violation for CallDatetimeNowWithoutTzinfo { impl Violation for CallDatetimeNowWithoutTzinfo {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -66,9 +66,9 @@ impl Violation for CallDatetimeNowWithoutTzinfo {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeFromtimestamp; pub struct CallDatetimeFromtimestamp;
);
impl Violation for CallDatetimeFromtimestamp { impl Violation for CallDatetimeFromtimestamp {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -78,9 +78,9 @@ impl Violation for CallDatetimeFromtimestamp {
} }
} }
define_violation!( #[violation]
pub struct CallDatetimeStrptimeWithoutZone; pub struct CallDatetimeStrptimeWithoutZone;
);
impl Violation for CallDatetimeStrptimeWithoutZone { impl Violation for CallDatetimeStrptimeWithoutZone {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -91,9 +91,9 @@ impl Violation for CallDatetimeStrptimeWithoutZone {
} }
} }
define_violation!( #[violation]
pub struct CallDateToday; pub struct CallDateToday;
);
impl Violation for CallDateToday { impl Violation for CallDateToday {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -104,9 +104,9 @@ impl Violation for CallDateToday {
} }
} }
define_violation!( #[violation]
pub struct CallDateFromtimestamp; pub struct CallDateFromtimestamp;
);
impl Violation for CallDateFromtimestamp { impl Violation for CallDateFromtimestamp {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Expr, Stmt};
use super::types::DebuggerUsingType; use super::types::DebuggerUsingType;
@ -10,11 +10,11 @@ use crate::violation::Violation;
// flake8-debugger // flake8-debugger
define_violation!( #[violation]
pub struct Debugger { pub struct Debugger {
pub using_type: DebuggerUsingType, pub using_type: DebuggerUsingType,
} }
);
impl Violation for Debugger { impl Violation for Debugger {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
use rustpython_parser::ast::Constant::Bool; use rustpython_parser::ast::Constant::Bool;
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind}; 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::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -10,41 +10,41 @@ use crate::violation::Violation;
use super::helpers; use super::helpers;
define_violation!( /// ## What it does
/// ## What it does /// Checks nullable string-based fields (like `CharField` and `TextField`)
/// Checks nullable string-based fields (like `CharField` and `TextField`) /// in Django models.
/// in Django models. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// If a string-based field is nullable, then your model will have two possible
/// 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
/// 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
/// 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.
/// 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
/// The Django convention is to use the empty string in lieu of `None` for /// string-based fields.
/// string-based fields. ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// from django.db import models
/// from django.db import models ///
/// ///
/// /// class MyModel(models.Model):
/// class MyModel(models.Model): /// field = models.CharField(max_length=255, null=True)
/// field = models.CharField(max_length=255, null=True) /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// from django.db import models
/// from django.db import models ///
/// ///
/// /// class MyModel(models.Model):
/// class MyModel(models.Model): /// field = models.CharField(max_length=255, default="")
/// field = models.CharField(max_length=255, default="") /// ```
/// ``` #[violation]
pub struct NullableModelStringField { pub struct NullableModelStringField {
pub field_name: String, pub field_name: String,
} }
);
impl Violation for NullableModelStringField { impl Violation for NullableModelStringField {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::{Constant, Expr, ExprKind};
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,46 +6,46 @@ use crate::checkers::ast::Checker;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( /// ## What it does
/// ## What it does /// Checks for the use of string literals in exception constructors.
/// Checks for the use of string literals in exception constructors. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Python includes the `raise` in the default traceback (and formatters
/// Python includes the `raise` in the default traceback (and formatters /// like Rich and IPython do too).
/// like Rich and IPython do too). ///
/// /// By using a string literal, the error message will be duplicated in the
/// By using a string literal, the error message will be duplicated in the /// traceback, which can make the traceback less readable.
/// traceback, which can make the traceback less readable. ///
/// /// ## Example
/// ## Example /// Given:
/// Given: /// ```python
/// ```python /// raise RuntimeError("'Some value' is incorrect")
/// raise RuntimeError("'Some value' is incorrect") /// ```
/// ``` ///
/// /// Python will produce a traceback like:
/// Python will produce a traceback like: /// ```console
/// ```console /// Traceback (most recent call last):
/// Traceback (most recent call last): /// File "tmp.py", line 2, in <module>
/// File "tmp.py", line 2, in <module> /// raise RuntimeError("Some value is incorrect")
/// raise RuntimeError("Some value is incorrect") /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` ///
/// /// Instead, assign the string to a variable:
/// Instead, assign the string to a variable: /// ```python
/// ```python /// msg = "'Some value' is incorrect"
/// msg = "'Some value' is incorrect" /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// ```
/// ``` ///
/// /// Which will produce a traceback like:
/// Which will produce a traceback like: /// ```console
/// ```console /// Traceback (most recent call last):
/// Traceback (most recent call last): /// File "tmp.py", line 3, in <module>
/// File "tmp.py", line 3, in <module> /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` #[violation]
pub struct RawStringInException; pub struct RawStringInException;
);
impl Violation for RawStringInException { impl Violation for RawStringInException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -53,47 +53,47 @@ impl Violation for RawStringInException {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for the use of f-strings in exception constructors.
/// Checks for the use of f-strings in exception constructors. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Python includes the `raise` in the default traceback (and formatters
/// Python includes the `raise` in the default traceback (and formatters /// like Rich and IPython do too).
/// like Rich and IPython do too). ///
/// /// By using an f-string, the error message will be duplicated in the
/// By using an f-string, the error message will be duplicated in the /// traceback, which can make the traceback less readable.
/// traceback, which can make the traceback less readable. ///
/// /// ## Example
/// ## Example /// Given:
/// Given: /// ```python
/// ```python /// sub = "Some value"
/// sub = "Some value" /// raise RuntimeError(f"{sub!r} is incorrect")
/// raise RuntimeError(f"{sub!r} is incorrect") /// ```
/// ``` ///
/// /// Python will produce a traceback like:
/// Python will produce a traceback like: /// ```console
/// ```console /// Traceback (most recent call last):
/// Traceback (most recent call last): /// File "tmp.py", line 2, in <module>
/// File "tmp.py", line 2, in <module> /// raise RuntimeError(f"{sub!r} is incorrect")
/// raise RuntimeError(f"{sub!r} is incorrect") /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` ///
/// /// Instead, assign the string to a variable:
/// Instead, assign the string to a variable: /// ```python
/// ```python /// sub = "Some value"
/// sub = "Some value" /// msg = f"{sub!r} is incorrect"
/// msg = f"{sub!r} is incorrect" /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// ```
/// ``` ///
/// /// Which will produce a traceback like:
/// Which will produce a traceback like: /// ```console
/// ```console /// File "tmp.py", line 3, in <module>
/// File "tmp.py", line 3, in <module> /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` #[violation]
pub struct FStringInException; pub struct FStringInException;
);
impl Violation for FStringInException { impl Violation for FStringInException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -101,49 +101,49 @@ impl Violation for FStringInException {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for the use of `.format` calls on string literals in exception
/// Checks for the use of `.format` calls on string literals in exception /// constructors.
/// constructors. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Python includes the `raise` in the default traceback (and formatters
/// Python includes the `raise` in the default traceback (and formatters /// like Rich and IPython do too).
/// like Rich and IPython do too). ///
/// /// By using a `.format` call, the error message will be duplicated in the
/// By using a `.format` call, the error message will be duplicated in the /// traceback, which can make the traceback less readable.
/// traceback, which can make the traceback less readable. ///
/// /// ## Example
/// ## Example /// Given:
/// Given: /// ```python
/// ```python /// sub = "Some value"
/// sub = "Some value" /// raise RuntimeError("'{}' is incorrect".format(sub))
/// raise RuntimeError("'{}' is incorrect".format(sub)) /// ```
/// ``` ///
/// /// Python will produce a traceback like:
/// Python will produce a traceback like: /// ```console
/// ```console /// Traceback (most recent call last):
/// Traceback (most recent call last): /// File "tmp.py", line 2, in <module>
/// File "tmp.py", line 2, in <module> /// raise RuntimeError("'{}' is incorrect".format(sub))
/// raise RuntimeError("'{}' is incorrect".format(sub)) /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` ///
/// /// Instead, assign the string to a variable:
/// Instead, assign the string to a variable: /// ```python
/// ```python /// sub = "Some value"
/// sub = "Some value" /// msg = "'{}' is incorrect".format(sub)
/// msg = "'{}' is incorrect".format(sub) /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// ```
/// ``` ///
/// /// Which will produce a traceback like:
/// Which will produce a traceback like: /// ```console
/// ```console /// Traceback (most recent call last):
/// Traceback (most recent call last): /// File "tmp.py", line 3, in <module>
/// File "tmp.py", line 3, in <module> /// raise RuntimeError(msg)
/// raise RuntimeError(msg) /// RuntimeError: 'Some value' is incorrect
/// RuntimeError: 'Some value' is incorrect /// ```
/// ``` #[violation]
pub struct DotFormatInException; pub struct DotFormatInException;
);
impl Violation for DotFormatInException { impl Violation for DotFormatInException {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -2,7 +2,7 @@
use std::path::Path; 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::ast::types::Range;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
@ -10,9 +10,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::is_executable; use crate::rules::flake8_executable::helpers::is_executable;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct ShebangMissingExecutableFile; pub struct ShebangMissingExecutableFile;
);
impl Violation for ShebangMissingExecutableFile { impl Violation for ShebangMissingExecutableFile {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::Location;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective; use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct ShebangNewline; pub struct ShebangNewline;
);
impl Violation for ShebangNewline { impl Violation for ShebangNewline {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -4,7 +4,7 @@ use std::path::Path;
use rustpython_parser::ast::Location; 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::ast::types::Range;
use crate::registry::Diagnostic; 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::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct ShebangNotExecutable; pub struct ShebangNotExecutable;
);
impl Violation for ShebangNotExecutable { impl Violation for ShebangNotExecutable {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::Location;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -6,9 +6,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective; use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( #[violation]
pub struct ShebangPython; pub struct ShebangPython;
);
impl Violation for ShebangPython { impl Violation for ShebangPython {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustpython_parser::ast::Location;
use crate::ast::types::Range; use crate::ast::types::Range;
@ -7,9 +7,9 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_executable::helpers::ShebangDirective; use crate::rules::flake8_executable::helpers::ShebangDirective;
use crate::violation::AlwaysAutofixableViolation; use crate::violation::AlwaysAutofixableViolation;
define_violation!( #[violation]
pub struct ShebangWhitespace; pub struct ShebangWhitespace;
);
impl AlwaysAutofixableViolation for ShebangWhitespace { impl AlwaysAutofixableViolation for ShebangWhitespace {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

@ -1,5 +1,5 @@
use itertools::Itertools; 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::ast::{Constant, Expr, ExprKind, Operator};
use rustpython_parser::lexer::LexResult; use rustpython_parser::lexer::LexResult;
use rustpython_parser::Tok; use rustpython_parser::Tok;
@ -9,30 +9,30 @@ use crate::registry::Diagnostic;
use crate::rules::flake8_implicit_str_concat::settings::Settings; use crate::rules::flake8_implicit_str_concat::settings::Settings;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( /// ## What it does
/// ## What it does /// Checks for implicitly concatenated strings on a single line.
/// Checks for implicitly concatenated strings on a single line. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// While it is valid Python syntax to concatenate multiple string or byte
/// While it is valid Python syntax to concatenate multiple string or byte /// literals implicitly (via whitespace delimiters), it is unnecessary and
/// literals implicitly (via whitespace delimiters), it is unnecessary and /// negatively affects code readability.
/// negatively affects code readability. ///
/// /// In some cases, the implicit concatenation may also be unintentional, as
/// In some cases, the implicit concatenation may also be unintentional, as /// autoformatters are capable of introducing single-line implicit
/// autoformatters are capable of introducing single-line implicit /// concatenations when collapsing long lines.
/// concatenations when collapsing long lines. ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// z = "The quick " "brown fox."
/// z = "The quick " "brown fox." /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// z = "The quick brown fox."
/// z = "The quick brown fox." /// ```
/// ``` #[violation]
pub struct SingleLineImplicitStringConcatenation; pub struct SingleLineImplicitStringConcatenation;
);
impl Violation for SingleLineImplicitStringConcatenation { impl Violation for SingleLineImplicitStringConcatenation {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -40,42 +40,42 @@ impl Violation for SingleLineImplicitStringConcatenation {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for implicitly concatenated strings that span multiple lines.
/// Checks for implicitly concatenated strings that span multiple lines. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// For string literals that wrap across multiple lines, PEP 8 recommends
/// For string literals that wrap across multiple lines, PEP 8 recommends /// the use of implicit string concatenation within parentheses instead of
/// the use of implicit string concatenation within parentheses instead of /// using a backslash for line continuation, as the former is more readable
/// using a backslash for line continuation, as the former is more readable /// than the latter.
/// than the latter. ///
/// /// By default, this rule will only trigger if the string literal is
/// By default, this rule will only trigger if the string literal is /// concatenated via a backslash. To disallow implicit string concatenation
/// concatenated via a backslash. To disallow implicit string concatenation /// altogether, set the `flake8-implicit-str-concat.allow-multiline` option
/// altogether, set the `flake8-implicit-str-concat.allow-multiline` option /// to `false`.
/// to `false`. ///
/// /// ## Options
/// ## Options /// - `flake8-implicit-str-concat.allow-multiline`
/// - `flake8-implicit-str-concat.allow-multiline` ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// z = "The quick brown fox jumps over the lazy "\
/// z = "The quick brown fox jumps over the lazy "\ /// "dog."
/// "dog." /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// z = (
/// z = ( /// "The quick brown fox jumps over the lazy "
/// "The quick brown fox jumps over the lazy " /// "dog."
/// "dog." /// )
/// ) /// ```
/// ``` ///
/// /// ## References
/// ## References /// - [PEP 8](https://peps.python.org/pep-0008/#maximum-line-length)
/// - [PEP 8](https://peps.python.org/pep-0008/#maximum-line-length) #[violation]
pub struct MultiLineImplicitStringConcatenation; pub struct MultiLineImplicitStringConcatenation;
);
impl Violation for MultiLineImplicitStringConcatenation { impl Violation for MultiLineImplicitStringConcatenation {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -83,33 +83,33 @@ impl Violation for MultiLineImplicitStringConcatenation {
} }
} }
define_violation!( /// ## What it does
/// ## What it does /// Checks for string literals that are explicitly concatenated (using the
/// Checks for string literals that are explicitly concatenated (using the /// `+` operator).
/// `+` operator). ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// For string literals that wrap across multiple lines, implicit string
/// For string literals that wrap across multiple lines, implicit string /// concatenation within parentheses is preferred over explicit
/// concatenation within parentheses is preferred over explicit /// concatenation using the `+` operator, as the former is more readable.
/// concatenation using the `+` operator, as the former is more readable. ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// z = (
/// z = ( /// "The quick brown fox jumps over the lazy "
/// "The quick brown fox jumps over the lazy " /// + "dog"
/// + "dog" /// )
/// ) /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// z = (
/// z = ( /// "The quick brown fox jumps over the lazy "
/// "The quick brown fox jumps over the lazy " /// "dog"
/// "dog" /// )
/// ) /// ```
/// ``` #[violation]
pub struct ExplicitStringConcatenation; pub struct ExplicitStringConcatenation;
);
impl Violation for ExplicitStringConcatenation { impl Violation for ExplicitStringConcatenation {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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 rustc_hash::FxHashMap;
use rustpython_parser::ast::Stmt; use rustpython_parser::ast::Stmt;
@ -6,30 +6,30 @@ use crate::ast::types::Range;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violation::Violation; use crate::violation::Violation;
define_violation!( /// ## What it does
/// ## What it does /// Checks for imports that are typically imported using a common convention,
/// Checks for imports that are typically imported using a common convention, /// like `import pandas as pd`, and enforces that convention.
/// like `import pandas as pd`, and enforces that convention. ///
/// /// ## Why is this bad?
/// ## Why is this bad? /// Consistency is good. Use a common convention for imports to make your code
/// Consistency is good. Use a common convention for imports to make your code /// more readable and idiomatic.
/// more readable and idiomatic. ///
/// /// For example, `import pandas as pd` is a common
/// For example, `import pandas as pd` is a common /// convention for importing the `pandas` library, and users typically expect
/// convention for importing the `pandas` library, and users typically expect /// Pandas to be aliased as `pd`.
/// Pandas to be aliased as `pd`. ///
/// /// ## Example
/// ## Example /// ```python
/// ```python /// import pandas
/// import pandas /// ```
/// ``` ///
/// /// Use instead:
/// Use instead: /// ```python
/// ```python /// import pandas as pd
/// import pandas as pd /// ```
/// ``` #[violation]
pub struct UnconventionalImportAlias(pub String, pub String); pub struct UnconventionalImportAlias(pub String, pub String);
);
impl Violation for UnconventionalImportAlias { impl Violation for UnconventionalImportAlias {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { 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}; use crate::violation::{AlwaysAutofixableViolation, Violation};
define_violation!( #[violation]
pub struct LoggingStringFormat; pub struct LoggingStringFormat;
);
impl Violation for LoggingStringFormat { impl Violation for LoggingStringFormat {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -12,9 +12,9 @@ impl Violation for LoggingStringFormat {
} }
} }
define_violation!( #[violation]
pub struct LoggingPercentFormat; pub struct LoggingPercentFormat;
);
impl Violation for LoggingPercentFormat { impl Violation for LoggingPercentFormat {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -22,9 +22,9 @@ impl Violation for LoggingPercentFormat {
} }
} }
define_violation!( #[violation]
pub struct LoggingStringConcat; pub struct LoggingStringConcat;
);
impl Violation for LoggingStringConcat { impl Violation for LoggingStringConcat {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -32,9 +32,9 @@ impl Violation for LoggingStringConcat {
} }
} }
define_violation!( #[violation]
pub struct LoggingFString; pub struct LoggingFString;
);
impl Violation for LoggingFString { impl Violation for LoggingFString {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -42,9 +42,9 @@ impl Violation for LoggingFString {
} }
} }
define_violation!( #[violation]
pub struct LoggingWarn; pub struct LoggingWarn;
);
impl AlwaysAutofixableViolation for LoggingWarn { impl AlwaysAutofixableViolation for LoggingWarn {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -56,9 +56,9 @@ impl AlwaysAutofixableViolation for LoggingWarn {
} }
} }
define_violation!( #[violation]
pub struct LoggingExtraAttrClash(pub String); pub struct LoggingExtraAttrClash(pub String);
);
impl Violation for LoggingExtraAttrClash { impl Violation for LoggingExtraAttrClash {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -69,9 +69,9 @@ impl Violation for LoggingExtraAttrClash {
} }
} }
define_violation!( #[violation]
pub struct LoggingExcInfo; pub struct LoggingExcInfo;
);
impl Violation for LoggingExcInfo { impl Violation for LoggingExcInfo {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
@ -79,9 +79,9 @@ impl Violation for LoggingExcInfo {
} }
} }
define_violation!( #[violation]
pub struct LoggingRedundantExcInfo; pub struct LoggingRedundantExcInfo;
);
impl Violation for LoggingRedundantExcInfo { impl Violation for LoggingRedundantExcInfo {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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