Implement F707 (DefaultExceptNotLast) (#101)

This commit is contained in:
Harutaka Kawamura 2022-09-05 00:55:06 +09:00 committed by GitHub
parent 8f6ab8b37a
commit b86414dc7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 0 deletions

View file

@ -118,6 +118,7 @@ OPTIONS:
| F634 | IfTuple | If test is a tuple, which is always `True` |
| F704 | YieldOutsideFunction | a `yield` or `yield from` statement outside of a function/method |
| F706 | ReturnOutsideFunction | a `return` statement outside of a function/method |
| F707 | DefaultExceptNotLast | an `except:` block as not the last exception handler |
| F821 | UndefinedName | Undefined name `...` |
| F822 | UndefinedExport | Undefined name `...` in `__all__` |
| F823 | UndefinedLocal | Local variable `...` referenced before assignment |

View file

@ -4,6 +4,7 @@ use ruff::checks::CheckKind;
fn main() {
let mut check_kinds: Vec<CheckKind> = vec![
CheckKind::AssertTuple,
CheckKind::DefaultExceptNotLast,
CheckKind::DuplicateArgumentName,
CheckKind::FStringMissingPlaceholders,
CheckKind::IfTuple,

46
resources/test/fixtures/F707.py vendored Normal file
View file

@ -0,0 +1,46 @@
try:
pass
except:
pass
except ValueError:
pass
try:
pass
except:
pass
except ValueError:
pass
finally:
pass
try:
pass
except:
pass
except ValueError:
pass
else:
pass
try:
pass
except:
pass
try:
pass
except ValueError:
pass
except:
pass
try:
pass
except ValueError:
pass
try:
pass
finally:
pass

View file

@ -10,6 +10,7 @@ select = [
"F634",
"F704",
"F706",
"F707",
"F821",
"F822",
"F823",

View file

@ -295,6 +295,23 @@ impl Visitor for Checker<'_> {
}
}
}
StmtKind::Try { handlers, .. } => {
if self
.settings
.select
.contains(CheckKind::DefaultExceptNotLast.code())
{
for (idx, handler) in handlers.iter().enumerate() {
let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
if type_.is_none() && idx < handlers.len() - 1 {
self.checks.push(Check {
kind: CheckKind::DefaultExceptNotLast,
location: handler.location,
});
}
}
}
}
_ => {}
}

View file

@ -16,6 +16,7 @@ pub enum CheckCode {
F634,
F704,
F706,
F707,
F821,
F822,
F823,
@ -38,6 +39,7 @@ impl FromStr for CheckCode {
"F634" => Ok(CheckCode::F634),
"F704" => Ok(CheckCode::F704),
"F706" => Ok(CheckCode::F706),
"F707" => Ok(CheckCode::F707),
"F821" => Ok(CheckCode::F821),
"F822" => Ok(CheckCode::F822),
"F823" => Ok(CheckCode::F823),
@ -61,6 +63,7 @@ impl CheckCode {
CheckCode::F634 => "F634",
CheckCode::F704 => "F704",
CheckCode::F706 => "F706",
CheckCode::F707 => "F707",
CheckCode::F821 => "F821",
CheckCode::F823 => "F823",
CheckCode::F822 => "F822",
@ -82,6 +85,7 @@ impl CheckCode {
CheckCode::F634 => &LintSource::AST,
CheckCode::F704 => &LintSource::AST,
CheckCode::F706 => &LintSource::AST,
CheckCode::F707 => &LintSource::AST,
CheckCode::F821 => &LintSource::AST,
CheckCode::F822 => &LintSource::AST,
CheckCode::F823 => &LintSource::AST,
@ -109,6 +113,7 @@ pub enum CheckKind {
LineTooLong,
RaiseNotImplemented,
ReturnOutsideFunction,
DefaultExceptNotLast,
UndefinedLocal(String),
UndefinedExport(String),
UndefinedName(String),
@ -130,6 +135,7 @@ impl CheckKind {
CheckKind::LineTooLong => "LineTooLong",
CheckKind::RaiseNotImplemented => "RaiseNotImplemented",
CheckKind::ReturnOutsideFunction => "ReturnOutsideFunction",
CheckKind::DefaultExceptNotLast => "DefaultExceptNotLast",
CheckKind::UndefinedLocal(_) => "UndefinedLocal",
CheckKind::UndefinedExport(_) => "UndefinedExport",
CheckKind::UndefinedName(_) => "UndefinedName",
@ -151,6 +157,7 @@ impl CheckKind {
CheckKind::LineTooLong => &CheckCode::E501,
CheckKind::RaiseNotImplemented => &CheckCode::F901,
CheckKind::ReturnOutsideFunction => &CheckCode::F706,
CheckKind::DefaultExceptNotLast => &CheckCode::F707,
CheckKind::UndefinedExport(_) => &CheckCode::F822,
CheckKind::UndefinedLocal(_) => &CheckCode::F823,
CheckKind::UndefinedName(_) => &CheckCode::F821,
@ -182,6 +189,9 @@ impl CheckKind {
CheckKind::ReturnOutsideFunction => {
"a `return` statement outside of a function/method".to_string()
}
CheckKind::DefaultExceptNotLast => {
"an `except:` block as not the last exception handler".to_string()
}
CheckKind::UndefinedExport(name) => {
format!("Undefined name `{name}` in `__all__`")
}

View file

@ -320,6 +320,47 @@ mod tests {
Ok(())
}
#[test]
fn f707() -> Result<()> {
let actual = check_path(
Path::new("./resources/test/fixtures/F707.py"),
&settings::Settings {
line_length: 88,
exclude: vec![],
select: BTreeSet::from([CheckCode::F707]),
},
&cache::Mode::None,
)?;
let expected = vec![
Message {
kind: CheckKind::DefaultExceptNotLast,
location: Location::new(3, 1),
filename: "./resources/test/fixtures/F707.py".to_string(),
},
Message {
kind: CheckKind::DefaultExceptNotLast,
location: Location::new(10, 1),
filename: "./resources/test/fixtures/F707.py".to_string(),
},
Message {
kind: CheckKind::DefaultExceptNotLast,
location: Location::new(19, 1),
filename: "./resources/test/fixtures/F707.py".to_string(),
},
Message {
kind: CheckKind::DefaultExceptNotLast,
location: Location::new(28, 1),
filename: "./resources/test/fixtures/F707.py".to_string(),
},
];
assert_eq!(actual.len(), expected.len());
for i in 0..actual.len() {
assert_eq!(actual[i], expected[i]);
}
Ok(())
}
#[test]
fn f821() -> Result<()> {
let actual = check_path(

View file

@ -245,6 +245,7 @@ other-attribute = 1
CheckCode::F634,
CheckCode::F704,
CheckCode::F706,
CheckCode::F707,
CheckCode::F821,
CheckCode::F822,
CheckCode::F823,

View file

@ -51,6 +51,7 @@ impl Settings {
CheckCode::F631,
CheckCode::F634,
CheckCode::F706,
CheckCode::F707,
CheckCode::F831,
CheckCode::F823,
CheckCode::F901,