mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
Avoid false-positives for parens-on-raise with futures.exception() (#10206)
## Summary As a heuristic, we now ignore function calls that "look like" method calls (e.g., `future.exception()`). Closes https://github.com/astral-sh/ruff/issues/10205.
This commit is contained in:
parent
7515196245
commit
ba7f6783e9
3 changed files with 51 additions and 6 deletions
|
@ -93,3 +93,15 @@ def func():
|
||||||
|
|
||||||
# OK
|
# OK
|
||||||
raise func()
|
raise func()
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
future = executor.submit(float, "a")
|
||||||
|
if future.exception():
|
||||||
|
raise future.exception()
|
||||||
|
|
||||||
|
|
||||||
|
# RSE102
|
||||||
|
future = executor.submit(float, "a")
|
||||||
|
if future.exception():
|
||||||
|
raise future.Exception()
|
||||||
|
|
|
@ -76,15 +76,34 @@ pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr:
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// `ctypes.WinError()` is a function, not a class. It's part of the standard library, so
|
if exception_type.is_none() {
|
||||||
// we might as well get it right.
|
// If the method name doesn't _look_ like a class (i.e., it's lowercase), it's
|
||||||
if exception_type.is_none()
|
// probably a function call, not a class.
|
||||||
&& checker
|
let identifier = match func.as_ref() {
|
||||||
|
Expr::Name(ast::ExprName { id, .. }) => Some(id.as_str()),
|
||||||
|
Expr::Attribute(ast::ExprAttribute { attr, .. }) => Some(attr.as_str()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if identifier.is_some_and(|identifier| {
|
||||||
|
identifier
|
||||||
|
.strip_prefix('_')
|
||||||
|
.unwrap_or(identifier)
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.is_some_and(char::is_lowercase)
|
||||||
|
}) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `ctypes.WinError()` is a function, not a class. It's part of the standard library, so
|
||||||
|
// we might as well get it right.
|
||||||
|
if checker
|
||||||
.semantic()
|
.semantic()
|
||||||
.resolve_call_path(func)
|
.resolve_call_path(func)
|
||||||
.is_some_and(|call_path| matches!(call_path.as_slice(), ["ctypes", "WinError"]))
|
.is_some_and(|call_path| matches!(call_path.as_slice(), ["ctypes", "WinError"]))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range());
|
||||||
|
|
|
@ -281,4 +281,18 @@ RSE102.py:84:10: RSE102 [*] Unnecessary parentheses on raised exception
|
||||||
86 86 | # OK
|
86 86 | # OK
|
||||||
87 87 | raise ctypes.WinError()
|
87 87 | raise ctypes.WinError()
|
||||||
|
|
||||||
|
RSE102.py:107:27: RSE102 [*] Unnecessary parentheses on raised exception
|
||||||
|
|
|
||||||
|
105 | future = executor.submit(float, "a")
|
||||||
|
106 | if future.exception():
|
||||||
|
107 | raise future.Exception()
|
||||||
|
| ^^ RSE102
|
||||||
|
|
|
||||||
|
= help: Remove unnecessary parentheses
|
||||||
|
|
||||||
|
ℹ Unsafe fix
|
||||||
|
104 104 | # RSE102
|
||||||
|
105 105 | future = executor.submit(float, "a")
|
||||||
|
106 106 | if future.exception():
|
||||||
|
107 |- raise future.Exception()
|
||||||
|
107 |+ raise future.Exception
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue