Implement F901

This commit is contained in:
Charles Marsh 2022-08-20 21:22:40 -04:00
parent 8d0d0bed0d
commit ac0eeee2a3
5 changed files with 90 additions and 15 deletions

View File

@ -0,0 +1,6 @@
def f() -> None:
raise NotImplemented()
def g() -> None:
raise NotImplemented

View File

@ -50,6 +50,37 @@ impl Visitor for Checker<'_> {
} }
} }
} }
StmtKind::Raise { exc, .. } => {
if self
.settings
.select
.contains(CheckKind::RaiseNotImplemented.code())
{
if let Some(expr) = exc {
match &expr.node {
ExprKind::Call { func, .. } => {
if let ExprKind::Name { id, .. } = &func.node {
if id == "NotImplemented" {
self.checks.push(Check {
kind: CheckKind::RaiseNotImplemented,
location: stmt.location,
});
}
}
}
ExprKind::Name { id, .. } => {
if id == "NotImplemented" {
self.checks.push(Check {
kind: CheckKind::RaiseNotImplemented,
location: stmt.location,
});
}
}
_ => {}
}
}
}
}
_ => {} _ => {}
} }

View File

@ -7,6 +7,7 @@ pub enum CheckCode {
F541, F541,
F634, F634,
F403, F403,
F901,
E501, E501,
} }
@ -17,6 +18,7 @@ impl CheckCode {
CheckCode::F541 => "F541", CheckCode::F541 => "F541",
CheckCode::F634 => "F634", CheckCode::F634 => "F634",
CheckCode::F403 => "F403", CheckCode::F403 => "F403",
CheckCode::F901 => "F901",
CheckCode::E501 => "E501", CheckCode::E501 => "E501",
} }
} }
@ -34,6 +36,7 @@ pub enum CheckKind {
FStringMissingPlaceholders, FStringMissingPlaceholders,
IfTuple, IfTuple,
ImportStarUsage, ImportStarUsage,
RaiseNotImplemented,
LineTooLong, LineTooLong,
} }
@ -45,6 +48,7 @@ impl CheckKind {
CheckCode::F541 => CheckKind::FStringMissingPlaceholders, CheckCode::F541 => CheckKind::FStringMissingPlaceholders,
CheckCode::F634 => CheckKind::IfTuple, CheckCode::F634 => CheckKind::IfTuple,
CheckCode::F403 => CheckKind::ImportStarUsage, CheckCode::F403 => CheckKind::ImportStarUsage,
CheckCode::F901 => CheckKind::RaiseNotImplemented,
CheckCode::E501 => CheckKind::LineTooLong, CheckCode::E501 => CheckKind::LineTooLong,
} }
} }
@ -56,6 +60,7 @@ impl CheckKind {
CheckKind::FStringMissingPlaceholders => &CheckCode::F541, CheckKind::FStringMissingPlaceholders => &CheckCode::F541,
CheckKind::IfTuple => &CheckCode::F634, CheckKind::IfTuple => &CheckCode::F634,
CheckKind::ImportStarUsage => &CheckCode::F403, CheckKind::ImportStarUsage => &CheckCode::F403,
CheckKind::RaiseNotImplemented => &CheckCode::F901,
CheckKind::LineTooLong => &CheckCode::E501, CheckKind::LineTooLong => &CheckCode::E501,
} }
} }
@ -67,6 +72,9 @@ impl CheckKind {
CheckKind::FStringMissingPlaceholders => "f-string without any placeholders", CheckKind::FStringMissingPlaceholders => "f-string without any placeholders",
CheckKind::IfTuple => "If test is a tuple, which is always `True`", CheckKind::IfTuple => "If test is a tuple, which is always `True`",
CheckKind::ImportStarUsage => "Unable to detect undefined names", CheckKind::ImportStarUsage => "Unable to detect undefined names",
CheckKind::RaiseNotImplemented => {
"'raise NotImplemented' should be 'raise NotImplementedError"
}
CheckKind::LineTooLong => "Line too long", CheckKind::LineTooLong => "Line too long",
} }
} }
@ -78,6 +86,7 @@ impl CheckKind {
CheckKind::FStringMissingPlaceholders => &LintSource::AST, CheckKind::FStringMissingPlaceholders => &LintSource::AST,
CheckKind::IfTuple => &LintSource::AST, CheckKind::IfTuple => &LintSource::AST,
CheckKind::ImportStarUsage => &LintSource::AST, CheckKind::ImportStarUsage => &LintSource::AST,
CheckKind::RaiseNotImplemented => &LintSource::AST,
CheckKind::LineTooLong => &LintSource::Lines, CheckKind::LineTooLong => &LintSource::Lines,
} }
} }

View File

@ -66,10 +66,7 @@ mod tests {
use anyhow::Result; use anyhow::Result;
use rustpython_parser::ast::Location; use rustpython_parser::ast::Location;
use crate::checks::CheckCode; use crate::checks::{CheckCode, CheckKind};
use crate::checks::CheckKind::{
DuplicateArgumentName, FStringMissingPlaceholders, IfTuple, ImportStarUsage, LineTooLong,
};
use crate::linter::check_path; use crate::linter::check_path;
use crate::message::Message; use crate::message::Message;
use crate::{cache, settings}; use crate::{cache, settings};
@ -87,17 +84,17 @@ mod tests {
)?; )?;
let expected = vec![ let expected = vec![
Message { Message {
kind: DuplicateArgumentName, kind: CheckKind::DuplicateArgumentName,
location: Location::new(1, 25), location: Location::new(1, 25),
filename: "./resources/test/src/duplicate_argument_name.py".to_string(), filename: "./resources/test/src/duplicate_argument_name.py".to_string(),
}, },
Message { Message {
kind: DuplicateArgumentName, kind: CheckKind::DuplicateArgumentName,
location: Location::new(5, 28), location: Location::new(5, 28),
filename: "./resources/test/src/duplicate_argument_name.py".to_string(), filename: "./resources/test/src/duplicate_argument_name.py".to_string(),
}, },
Message { Message {
kind: DuplicateArgumentName, kind: CheckKind::DuplicateArgumentName,
location: Location::new(9, 27), location: Location::new(9, 27),
filename: "./resources/test/src/duplicate_argument_name.py".to_string(), filename: "./resources/test/src/duplicate_argument_name.py".to_string(),
}, },
@ -123,17 +120,17 @@ mod tests {
)?; )?;
let expected = vec![ let expected = vec![
Message { Message {
kind: FStringMissingPlaceholders, kind: CheckKind::FStringMissingPlaceholders,
location: Location::new(4, 7), location: Location::new(4, 7),
filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(), filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(),
}, },
Message { Message {
kind: FStringMissingPlaceholders, kind: CheckKind::FStringMissingPlaceholders,
location: Location::new(5, 7), location: Location::new(5, 7),
filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(), filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(),
}, },
Message { Message {
kind: FStringMissingPlaceholders, kind: CheckKind::FStringMissingPlaceholders,
location: Location::new(7, 7), location: Location::new(7, 7),
filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(), filename: "./resources/test/src/f_string_missing_placeholders.py".to_string(),
}, },
@ -159,12 +156,12 @@ mod tests {
)?; )?;
let expected = vec![ let expected = vec![
Message { Message {
kind: IfTuple, kind: CheckKind::IfTuple,
location: Location::new(1, 1), location: Location::new(1, 1),
filename: "./resources/test/src/if_tuple.py".to_string(), filename: "./resources/test/src/if_tuple.py".to_string(),
}, },
Message { Message {
kind: IfTuple, kind: CheckKind::IfTuple,
location: Location::new(7, 5), location: Location::new(7, 5),
filename: "./resources/test/src/if_tuple.py".to_string(), filename: "./resources/test/src/if_tuple.py".to_string(),
}, },
@ -190,12 +187,12 @@ mod tests {
)?; )?;
let expected = vec![ let expected = vec![
Message { Message {
kind: ImportStarUsage, kind: CheckKind::ImportStarUsage,
location: Location::new(1, 1), location: Location::new(1, 1),
filename: "./resources/test/src/import_star_usage.py".to_string(), filename: "./resources/test/src/import_star_usage.py".to_string(),
}, },
Message { Message {
kind: ImportStarUsage, kind: CheckKind::ImportStarUsage,
location: Location::new(2, 1), location: Location::new(2, 1),
filename: "./resources/test/src/import_star_usage.py".to_string(), filename: "./resources/test/src/import_star_usage.py".to_string(),
}, },
@ -208,6 +205,37 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn raise_not_implemented() -> Result<()> {
let actual = check_path(
&Path::new("./resources/test/src/raise_not_implemented.py"),
&settings::Settings {
line_length: 88,
exclude: vec![],
select: BTreeSet::from([CheckCode::F901]),
},
&cache::Mode::None,
)?;
let expected = vec![
Message {
kind: CheckKind::RaiseNotImplemented,
location: Location::new(2, 5),
filename: "./resources/test/src/raise_not_implemented.py".to_string(),
},
Message {
kind: CheckKind::RaiseNotImplemented,
location: Location::new(6, 5),
filename: "./resources/test/src/raise_not_implemented.py".to_string(),
},
];
assert_eq!(actual.len(), expected.len());
for i in 0..actual.len() {
assert_eq!(actual[i], expected[i]);
}
Ok(())
}
#[test] #[test]
fn line_too_long() -> Result<()> { fn line_too_long() -> Result<()> {
let actual = check_path( let actual = check_path(
@ -220,7 +248,7 @@ mod tests {
&cache::Mode::None, &cache::Mode::None,
)?; )?;
let expected = vec![Message { let expected = vec![Message {
kind: LineTooLong, kind: CheckKind::LineTooLong,
location: Location::new(5, 89), location: Location::new(5, 89),
filename: "./resources/test/src/line_too_long.py".to_string(), filename: "./resources/test/src/line_too_long.py".to_string(),
}]; }];

View File

@ -45,6 +45,7 @@ impl Settings {
CheckCode::F541, CheckCode::F541,
CheckCode::F634, CheckCode::F634,
CheckCode::F403, CheckCode::F403,
CheckCode::F901,
CheckCode::E501, CheckCode::E501,
]) ])
}), }),