From 9097bf5ed6cd3d5a96ec95436e019e1997ec69a4 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 5 Sep 2022 12:42:00 -0400 Subject: [PATCH] Implement E902 (IOError) --- README.md | 1 + examples/generate_rules_table.rs | 1 + resources/test/fixtures/pyproject.toml | 1 + src/checks.rs | 12 ++++++++++++ src/main.rs | 19 +++++++++++++++++-- src/pyproject.rs | 1 + src/settings.rs | 1 + 7 files changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3cba4fe14e..e059c468e0 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ lint rules that are obviated by Black (e.g., stylistic rules). | ---- | ----- | ------- | | E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | | E501 | LineTooLong | Line too long | +| E902 | IOError | No such file or directory: `...` | | F401 | UnusedImport | `...` imported but unused | | F403 | ImportStarUsage | Unable to detect undefined names | | F541 | FStringMissingPlaceholders | f-string without any placeholders | diff --git a/examples/generate_rules_table.rs b/examples/generate_rules_table.rs index 5959966e4a..f442973584 100644 --- a/examples/generate_rules_table.rs +++ b/examples/generate_rules_table.rs @@ -8,6 +8,7 @@ fn main() { CheckKind::DuplicateArgumentName, CheckKind::FStringMissingPlaceholders, CheckKind::IfTuple, + CheckKind::IOError("...".to_string()), CheckKind::ImportStarUsage, CheckKind::LineTooLong, CheckKind::ModuleImportNotAtTopOfFile, diff --git a/resources/test/fixtures/pyproject.toml b/resources/test/fixtures/pyproject.toml index 135ca6f6fd..0153968bf5 100644 --- a/resources/test/fixtures/pyproject.toml +++ b/resources/test/fixtures/pyproject.toml @@ -4,6 +4,7 @@ exclude = ["excluded.py", "**/migrations"] select = [ "E402", "E501", + "E902", "F401", "F403", "F541", diff --git a/src/checks.rs b/src/checks.rs index 424d2443ef..a70f41269c 100644 --- a/src/checks.rs +++ b/src/checks.rs @@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize}; pub enum CheckCode { E402, E501, + E902, F401, F403, F541, @@ -35,6 +36,7 @@ impl FromStr for CheckCode { match s { "E402" => Ok(CheckCode::E402), "E501" => Ok(CheckCode::E501), + "E902" => Ok(CheckCode::E902), "F401" => Ok(CheckCode::F401), "F403" => Ok(CheckCode::F403), "F541" => Ok(CheckCode::F541), @@ -61,6 +63,7 @@ impl CheckCode { match self { CheckCode::E402 => "E402", CheckCode::E501 => "E501", + CheckCode::E902 => "E902", CheckCode::F401 => "F401", CheckCode::F403 => "F403", CheckCode::F541 => "F541", @@ -85,6 +88,7 @@ impl CheckCode { match self { CheckCode::E402 => &LintSource::AST, CheckCode::E501 => &LintSource::Lines, + CheckCode::E902 => &LintSource::FileSystem, CheckCode::F401 => &LintSource::AST, CheckCode::F403 => &LintSource::AST, CheckCode::F541 => &LintSource::AST, @@ -109,6 +113,7 @@ impl CheckCode { pub enum LintSource { AST, Lines, + FileSystem, } #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -117,6 +122,7 @@ pub enum CheckKind { DefaultExceptNotLast, DuplicateArgumentName, FStringMissingPlaceholders, + IOError(String), IfTuple, ImportStarUsage, LineTooLong, @@ -141,6 +147,7 @@ impl CheckKind { CheckKind::DefaultExceptNotLast => "DefaultExceptNotLast", CheckKind::DuplicateArgumentName => "DuplicateArgumentName", CheckKind::FStringMissingPlaceholders => "FStringMissingPlaceholders", + CheckKind::IOError(_) => "IOError", CheckKind::IfTuple => "IfTuple", CheckKind::ImportStarUsage => "ImportStarUsage", CheckKind::LineTooLong => "LineTooLong", @@ -165,6 +172,7 @@ impl CheckKind { CheckKind::DefaultExceptNotLast => &CheckCode::F707, CheckKind::DuplicateArgumentName => &CheckCode::F831, CheckKind::FStringMissingPlaceholders => &CheckCode::F541, + CheckKind::IOError(_) => &CheckCode::E902, CheckKind::IfTuple => &CheckCode::F634, CheckKind::ImportStarUsage => &CheckCode::F403, CheckKind::LineTooLong => &CheckCode::E501, @@ -197,6 +205,9 @@ impl CheckKind { CheckKind::FStringMissingPlaceholders => { "f-string without any placeholders".to_string() } + CheckKind::IOError(name) => { + format!("No such file or directory: `{name}`") + } CheckKind::IfTuple => "If test is a tuple, which is always `True`".to_string(), CheckKind::ImportStarUsage => "Unable to detect undefined names".to_string(), CheckKind::LineTooLong => "Line too long".to_string(), @@ -242,6 +253,7 @@ impl CheckKind { CheckKind::DuplicateArgumentName => false, CheckKind::FStringMissingPlaceholders => false, CheckKind::IfTuple => false, + CheckKind::IOError(_) => false, CheckKind::ImportStarUsage => false, CheckKind::LineTooLong => false, CheckKind::ModuleImportNotAtTopOfFile => false, diff --git a/src/main.rs b/src/main.rs index 5435decaad..7e6e6e41c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ use ::ruff::logging::set_up_logging; use ::ruff::message::Message; use ::ruff::settings::Settings; use ::ruff::tell_user; +use ruff::checks::CheckKind; const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME"); const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -62,7 +63,7 @@ fn run_once( ) -> Result> { // Collect all the files to check. let start = Instant::now(); - let files: Vec = files + let paths: Vec = files .iter() .flat_map(|path| iter_python_files(path, &settings.exclude)) .collect(); @@ -70,7 +71,7 @@ fn run_once( debug!("Identified files to lint in: {:?}", duration); let start = Instant::now(); - let mut messages: Vec = files + let mut messages: Vec = paths .par_iter() .map(|entry| { lint_path(entry.path(), settings, &cache.into(), &autofix.into()).unwrap_or_else(|e| { @@ -80,6 +81,20 @@ fn run_once( }) .flatten() .collect(); + + if settings.select.contains(&CheckCode::E902) { + for file in files { + if !file.exists() { + messages.push(Message { + kind: CheckKind::IOError(file.to_string_lossy().to_string()), + fixed: false, + location: Default::default(), + filename: file.to_string_lossy().to_string(), + }) + } + } + } + messages.sort_unstable(); let duration = start.elapsed(); debug!("Checked files in: {:?}", duration); diff --git a/src/pyproject.rs b/src/pyproject.rs index e40a6b4fbc..e7d98bad62 100644 --- a/src/pyproject.rs +++ b/src/pyproject.rs @@ -239,6 +239,7 @@ other-attribute = 1 select: Some(BTreeSet::from([ CheckCode::E402, CheckCode::E501, + CheckCode::E902, CheckCode::F401, CheckCode::F403, CheckCode::F541, diff --git a/src/settings.rs b/src/settings.rs index c601722a8e..596e87b084 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -46,6 +46,7 @@ impl Settings { BTreeSet::from([ CheckCode::E402, CheckCode::E501, + CheckCode::E902, CheckCode::F401, CheckCode::F403, CheckCode::F541,