Skip to content

Commit dce25da

Browse files
authored
[flake8-errmsg] Exclude typing.cast from EM101 (#19656)
## Summary Fixes #19596
1 parent 06cd249 commit dce25da

File tree

4 files changed

+97
-68
lines changed

4 files changed

+97
-68
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_errmsg/EM.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,25 @@ def f_multi_line_string2():
8888
example="example"
8989
)
9090
)
91+
92+
93+
def raise_typing_cast_exception():
94+
import typing
95+
raise typing.cast("Exception", None)
96+
97+
98+
def f_typing_cast_excluded():
99+
from typing import cast
100+
raise cast(RuntimeError, "This should not trigger EM101")
101+
102+
103+
def f_typing_cast_excluded_import():
104+
import typing
105+
raise typing.cast(RuntimeError, "This should not trigger EM101")
106+
107+
108+
def f_typing_cast_excluded_aliased():
109+
from typing import cast as my_cast
110+
raise my_cast(RuntimeError, "This should not trigger EM101")
111+
112+

crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs

Lines changed: 69 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -182,60 +182,47 @@ impl Violation for DotFormatInException {
182182

183183
/// EM101, EM102, EM103
184184
pub(crate) fn string_in_exception(checker: &Checker, stmt: &Stmt, exc: &Expr) {
185-
if let Expr::Call(ast::ExprCall {
185+
let Expr::Call(ast::ExprCall {
186+
func,
186187
arguments: Arguments { args, .. },
187188
..
188189
}) = exc
189-
{
190-
if let Some(first) = args.first() {
191-
match first {
192-
// Check for string literals.
193-
Expr::StringLiteral(ast::ExprStringLiteral { value: string, .. }) => {
194-
if checker.is_rule_enabled(Rule::RawStringInException) {
195-
if string.len() >= checker.settings().flake8_errmsg.max_string_length {
196-
let mut diagnostic =
197-
checker.report_diagnostic(RawStringInException, first.range());
198-
if let Some(indentation) =
199-
whitespace::indentation(checker.source(), stmt)
200-
{
201-
diagnostic.set_fix(generate_fix(
202-
stmt,
203-
first,
204-
indentation,
205-
checker.stylist(),
206-
checker.locator(),
207-
));
208-
}
209-
}
210-
}
211-
}
212-
// Check for byte string literals.
213-
Expr::BytesLiteral(ast::ExprBytesLiteral { value: bytes, .. }) => {
214-
if checker.settings().rules.enabled(Rule::RawStringInException) {
215-
if bytes.len() >= checker.settings().flake8_errmsg.max_string_length
216-
&& is_raise_exception_byte_string_enabled(checker.settings())
217-
{
218-
let mut diagnostic =
219-
checker.report_diagnostic(RawStringInException, first.range());
220-
if let Some(indentation) =
221-
whitespace::indentation(checker.source(), stmt)
222-
{
223-
diagnostic.set_fix(generate_fix(
224-
stmt,
225-
first,
226-
indentation,
227-
checker.stylist(),
228-
checker.locator(),
229-
));
230-
}
190+
else {
191+
return;
192+
};
193+
194+
if checker.semantic().match_typing_expr(func, "cast") {
195+
return;
196+
}
197+
198+
if let Some(first) = args.first() {
199+
match first {
200+
// Check for string literals.
201+
Expr::StringLiteral(ast::ExprStringLiteral { value: string, .. }) => {
202+
if checker.is_rule_enabled(Rule::RawStringInException) {
203+
if string.len() >= checker.settings().flake8_errmsg.max_string_length {
204+
let mut diagnostic =
205+
checker.report_diagnostic(RawStringInException, first.range());
206+
if let Some(indentation) = whitespace::indentation(checker.source(), stmt) {
207+
diagnostic.set_fix(generate_fix(
208+
stmt,
209+
first,
210+
indentation,
211+
checker.stylist(),
212+
checker.locator(),
213+
));
231214
}
232215
}
233216
}
234-
// Check for f-strings.
235-
Expr::FString(_) => {
236-
if checker.is_rule_enabled(Rule::FStringInException) {
217+
}
218+
// Check for byte string literals.
219+
Expr::BytesLiteral(ast::ExprBytesLiteral { value: bytes, .. }) => {
220+
if checker.settings().rules.enabled(Rule::RawStringInException) {
221+
if bytes.len() >= checker.settings().flake8_errmsg.max_string_length
222+
&& is_raise_exception_byte_string_enabled(checker.settings())
223+
{
237224
let mut diagnostic =
238-
checker.report_diagnostic(FStringInException, first.range());
225+
checker.report_diagnostic(RawStringInException, first.range());
239226
if let Some(indentation) = whitespace::indentation(checker.source(), stmt) {
240227
diagnostic.set_fix(generate_fix(
241228
stmt,
@@ -247,32 +234,46 @@ pub(crate) fn string_in_exception(checker: &Checker, stmt: &Stmt, exc: &Expr) {
247234
}
248235
}
249236
}
250-
// Check for .format() calls.
251-
Expr::Call(ast::ExprCall { func, .. }) => {
252-
if checker.is_rule_enabled(Rule::DotFormatInException) {
253-
if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) =
254-
func.as_ref()
255-
{
256-
if attr == "format" && value.is_literal_expr() {
257-
let mut diagnostic =
258-
checker.report_diagnostic(DotFormatInException, first.range());
259-
if let Some(indentation) =
260-
whitespace::indentation(checker.source(), stmt)
261-
{
262-
diagnostic.set_fix(generate_fix(
263-
stmt,
264-
first,
265-
indentation,
266-
checker.stylist(),
267-
checker.locator(),
268-
));
269-
}
237+
}
238+
// Check for f-strings.
239+
Expr::FString(_) => {
240+
if checker.is_rule_enabled(Rule::FStringInException) {
241+
let mut diagnostic =
242+
checker.report_diagnostic(FStringInException, first.range());
243+
if let Some(indentation) = whitespace::indentation(checker.source(), stmt) {
244+
diagnostic.set_fix(generate_fix(
245+
stmt,
246+
first,
247+
indentation,
248+
checker.stylist(),
249+
checker.locator(),
250+
));
251+
}
252+
}
253+
}
254+
// Check for .format() calls.
255+
Expr::Call(ast::ExprCall { func, .. }) => {
256+
if checker.is_rule_enabled(Rule::DotFormatInException) {
257+
if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() {
258+
if attr == "format" && value.is_literal_expr() {
259+
let mut diagnostic =
260+
checker.report_diagnostic(DotFormatInException, first.range());
261+
if let Some(indentation) =
262+
whitespace::indentation(checker.source(), stmt)
263+
{
264+
diagnostic.set_fix(generate_fix(
265+
stmt,
266+
first,
267+
indentation,
268+
checker.stylist(),
269+
checker.locator(),
270+
));
270271
}
271272
}
272273
}
273274
}
274-
_ => {}
275275
}
276+
_ => {}
276277
}
277278
}
278279
}

crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__custom.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,6 @@ EM.py:84:9: EM103 [*] Exception must not use a `.format()` string directly, assi
278278
91 |+ raise RuntimeError(
279279
92 |+ msg
280280
93 |+ )
281+
91 94 |
282+
92 95 |
283+
93 96 | def raise_typing_cast_exception():

crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__defaults.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,6 @@ EM.py:84:9: EM103 [*] Exception must not use a `.format()` string directly, assi
343343
91 |+ raise RuntimeError(
344344
92 |+ msg
345345
93 |+ )
346+
91 94 |
347+
92 95 |
348+
93 96 | def raise_typing_cast_exception():

0 commit comments

Comments
 (0)