Remove `B904`'s lowercase exemption (#5751)

## Summary

It looks like bugbear, [from the
start](https://github.com/PyCQA/flake8-bugbear/pull/181#issuecomment-904314876),
has had an exemption here to exempt `raise lower_case_var`. I looked at
Hypothesis and Trio, which are mentioned in that issue, and Hypothesis
has exactly one case of this, and Trio has none, so IMO it doesn't seem
worth special-casing.

Closes https://github.com/astral-sh/ruff/issues/5664.
This commit is contained in:
Charlie Marsh 2023-07-14 11:46:21 -04:00 committed by GitHub
parent 816f7644a9
commit 513de13c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 29 deletions

View File

@ -14,9 +14,10 @@ except AssertionError:
except Exception as err:
assert err
raise Exception("No cause here...")
except BaseException as base_err:
# Might use this instead of bare raise with the `.with_traceback()` method
raise base_err
except BaseException as err:
raise err
except BaseException as err:
raise some_other_err
finally:
raise Exception("Nothing to chain from, so no warning here")

View File

@ -3897,7 +3897,7 @@ where
}
}
if self.enabled(Rule::RaiseWithoutFromInsideExcept) {
flake8_bugbear::rules::raise_without_from_inside_except(self, body);
flake8_bugbear::rules::raise_without_from_inside_except(self, name, body);
}
if self.enabled(Rule::BlindExcept) {
flake8_blind_except::rules::blind_except(self, type_.as_deref(), name, body);

View File

@ -1,10 +1,10 @@
use rustpython_parser::ast::{self, Expr, Stmt};
use rustpython_parser::ast;
use rustpython_parser::ast::Stmt;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::RaiseStatementVisitor;
use ruff_python_ast::statement_visitor::StatementVisitor;
use ruff_python_stdlib::str::is_cased_lowercase;
use crate::checkers::ast::Checker;
@ -60,7 +60,11 @@ impl Violation for RaiseWithoutFromInsideExcept {
}
/// B904
pub(crate) fn raise_without_from_inside_except(checker: &mut Checker, body: &[Stmt]) {
pub(crate) fn raise_without_from_inside_except(
checker: &mut Checker,
name: Option<&str>,
body: &[Stmt],
) {
let raises = {
let mut visitor = RaiseStatementVisitor::default();
visitor.visit_body(body);
@ -70,14 +74,28 @@ pub(crate) fn raise_without_from_inside_except(checker: &mut Checker, body: &[St
for (range, exc, cause) in raises {
if cause.is_none() {
if let Some(exc) = exc {
match exc {
Expr::Name(ast::ExprName { id, .. }) if is_cased_lowercase(id) => {}
_ => {
checker
.diagnostics
.push(Diagnostic::new(RaiseWithoutFromInsideExcept, range));
// If the raised object is bound to the same name, it's a re-raise, which is
// allowed (but may be flagged by other diagnostics).
//
// For example:
// ```python
// try:
// ...
// except ValueError as exc:
// raise exc
// ```
if let Some(name) = name {
if exc
.as_name_expr()
.map_or(false, |ast::ExprName { id, .. }| name == id)
{
continue;
}
}
checker
.diagnostics
.push(Diagnostic::new(RaiseWithoutFromInsideExcept, range));
}
}
}

View File

@ -27,33 +27,43 @@ B904.py:16:5: B904 Within an `except` clause, raise exceptions with `raise ... f
15 | assert err
16 | raise Exception("No cause here...")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B904
17 | except BaseException as base_err:
18 | # Might use this instead of bare raise with the `.with_traceback()` method
17 | except BaseException as err:
18 | raise err
|
B904.py:62:9: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
B904.py:20:5: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
|
60 | except Exception as e:
61 | if ...:
62 | raise RuntimeError("boom!")
18 | raise err
19 | except BaseException as err:
20 | raise some_other_err
| ^^^^^^^^^^^^^^^^^^^^ B904
21 | finally:
22 | raise Exception("Nothing to chain from, so no warning here")
|
B904.py:63:9: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
|
61 | except Exception as e:
62 | if ...:
63 | raise RuntimeError("boom!")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ B904
63 | else:
64 | raise RuntimeError("bang!")
64 | else:
65 | raise RuntimeError("bang!")
|
B904.py:64:9: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
B904.py:65:9: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
|
62 | raise RuntimeError("boom!")
63 | else:
64 | raise RuntimeError("bang!")
63 | raise RuntimeError("boom!")
64 | else:
65 | raise RuntimeError("bang!")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ B904
|
B904.py:72:13: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
B904.py:73:13: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
|
70 | match 0:
71 | case 0:
72 | raise RuntimeError("boom!")
71 | match 0:
72 | case 0:
73 | raise RuntimeError("boom!")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ B904
|