diff --git a/README.md b/README.md index c008ce28bf..14578e6cd3 100644 --- a/README.md +++ b/README.md @@ -1125,9 +1125,9 @@ For more, see [flake8-errmsg](https://pypi.org/project/flake8-errmsg/) on PyPI. | Code | Name | Message | Fix | | ---- | ---- | ------- | --- | -| EM101 | raw-string-in-exception | Exception must not use a string literal, assign to variable first | | -| EM102 | f-string-in-exception | Exception must not use an f-string literal, assign to variable first | | -| EM103 | dot-format-in-exception | Exception must not use a `.format()` string directly, assign to variable first | | +| EM101 | [raw-string-in-exception](https://beta.ruff.rs/docs/rules/raw-string-in-exception/) | Exception must not use a string literal, assign to variable first | | +| EM102 | [f-string-in-exception](https://beta.ruff.rs/docs/rules/f-string-in-exception/) | Exception must not use an f-string literal, assign to variable first | | +| EM103 | [dot-format-in-exception](https://beta.ruff.rs/docs/rules/dot-format-in-exception/) | Exception must not use a `.format()` string directly, assign to variable first | | ### flake8-executable (EXE) diff --git a/clippy.toml b/clippy.toml index 6f74513ca1..05fb13a21d 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -doc-valid-idents = ["StackOverflow", "CodeQL", ".."] +doc-valid-idents = ["StackOverflow", "CodeQL", "IPython", ".."] diff --git a/crates/ruff/src/rules/flake8_errmsg/rules.rs b/crates/ruff/src/rules/flake8_errmsg/rules.rs index e18cce296a..1c1c130bdb 100644 --- a/crates/ruff/src/rules/flake8_errmsg/rules.rs +++ b/crates/ruff/src/rules/flake8_errmsg/rules.rs @@ -7,6 +7,43 @@ use crate::registry::{Diagnostic, Rule}; use crate::violation::Violation; define_violation!( + /// ## What it does + /// Checks for the use of string literals in exception constructors. + /// + /// ## Why is this bad? + /// Python includes the `raise` in the default traceback (and formatters + /// like Rich and IPython do too). + /// + /// By using a string literal, the error message will be duplicated in the + /// traceback, which can make the traceback less readable. + /// + /// ## Example + /// Given: + /// ```python + /// raise RuntimeError("'Some value' is incorrect") + /// ``` + /// + /// Python will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 2, in + /// raise RuntimeError("Some value is incorrect") + /// RuntimeError: 'Some value' is incorrect + /// ``` + /// + /// Instead, assign the string to a variable: + /// ```python + /// msg = "'Some value' is incorrect" + /// raise RuntimeError(msg) + /// ``` + /// + /// Which will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 3, in + /// raise RuntimeError(msg) + /// RuntimeError: 'Some value' is incorrect + /// ``` pub struct RawStringInException; ); impl Violation for RawStringInException { @@ -17,6 +54,45 @@ impl Violation for RawStringInException { } define_violation!( + /// ## What it does + /// Checks for the use of f-strings in exception constructors. + /// + /// ## Why is this bad? + /// Python includes the `raise` in the default traceback (and formatters + /// like Rich and IPython do too). + /// + /// By using an f-string, the error message will be duplicated in the + /// traceback, which can make the traceback less readable. + /// + /// ## Example + /// Given: + /// ```python + /// sub = "Some value" + /// raise RuntimeError(f"{sub!r} is incorrect") + /// ``` + /// + /// Python will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 2, in + /// raise RuntimeError(f"{sub!r} is incorrect") + /// RuntimeError: 'Some value' is incorrect + /// ``` + /// + /// Instead, assign the string to a variable: + /// ```python + /// sub = "Some value" + /// msg = f"{sub!r} is incorrect" + /// raise RuntimeError(msg) + /// ``` + /// + /// Which will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 3, in + /// raise RuntimeError(msg) + /// RuntimeError: 'Some value' is incorrect + /// ``` pub struct FStringInException; ); impl Violation for FStringInException { @@ -27,6 +103,46 @@ impl Violation for FStringInException { } define_violation!( + /// ## What it does + /// Checks for the use of `.format` calls on string literals in exception + /// constructors. + /// + /// ## Why is this bad? + /// Python includes the `raise` in the default traceback (and formatters + /// like Rich and IPython do too). + /// + /// By using a `.format` call, the error message will be duplicated in the + /// traceback, which can make the traceback less readable. + /// + /// ## Example + /// Given: + /// ```python + /// sub = "Some value" + /// raise RuntimeError("'{}' is incorrect".format(sub)) + /// ``` + /// + /// Python will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 2, in + /// raise RuntimeError("'{}' is incorrect".format(sub)) + /// RuntimeError: 'Some value' is incorrect + /// ``` + /// + /// Instead, assign the string to a variable: + /// ```python + /// sub = "Some value" + /// msg = "'{}' is incorrect".format(sub) + /// raise RuntimeError(msg) + /// ``` + /// + /// Which will produce a traceback like: + /// ```python + /// Traceback (most recent call last): + /// File "tmp.py", line 3, in + /// raise RuntimeError(msg) + /// RuntimeError: 'Some value' is incorrect + /// ``` pub struct DotFormatInException; ); impl Violation for DotFormatInException {