Skip to content

Commit

Permalink
Add support for noqa pragmas (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh authored Aug 16, 2022
1 parent f01707b commit 3b1b53d
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 15 deletions.
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ colored = { version = "2.0.0" }
fern = { version = "0.6.1" }
log = { version = "0.4.17" }
notify = { version = "4.0.17" }
pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37"] }
rayon = { version = "1.5.3" }
regex = { version = "1.6.0" }
rustpython-parser = { git = "https://github.com/RustPython/RustPython.git", rev = "dff916d45c5d13074d21ad329a5ab68a6499426a" }
serde = { version = "1.0.143", features = ["derive"] }
serde_json = { version = "1.0.83" }
walkdir = { version = "2.3.2" }
pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37"] }
5 changes: 5 additions & 0 deletions resources/test/src/import_star_usage.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
from if_tuple import *
from if_tuple import * # noqa: E501

from if_tuple import * # noqa
from if_tuple import * # noqa: F403
from if_tuple import * # noqa: F403, E501
4 changes: 2 additions & 2 deletions src/check_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ impl Visitor for Checker {
fn visit_arguments(&mut self, arguments: &Arguments) {
// Collect all the arguments into a single vector.
let mut all_arguments: Vec<&Arg> = arguments
.posonlyargs
.args
.iter()
.chain(arguments.posonlyargs.iter())
.chain(arguments.kwonlyargs.iter())
.chain(arguments.args.iter())
.collect();
if let Some(arg) = &arguments.vararg {
all_arguments.push(arg);
Expand Down
5 changes: 3 additions & 2 deletions src/check_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ use rustpython_parser::ast::Location;

use crate::checks::Check;
use crate::checks::CheckKind::LineTooLong;
use crate::settings::MAX_LINE_LENGTH;

pub fn check_lines(contents: &str) -> Vec<Check> {
contents
.lines()
.enumerate()
.filter_map(|(row, line)| {
if line.len() > 79 {
if line.len() > *MAX_LINE_LENGTH {
Some(Check {
kind: LineTooLong,
location: Location::new(row + 1, 79 + 1),
location: Location::new(row + 1, MAX_LINE_LENGTH + 1),
})
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl CheckKind {
CheckKind::DuplicateArgumentName => "Duplicate argument name in function definition",
CheckKind::IfTuple => "If test is a tuple, which is always `True`",
CheckKind::ImportStarUsage => "Unable to detect undefined names",
CheckKind::LineTooLong => "Line too long (> 79 characters)",
CheckKind::LineTooLong => "Line too long",
}
}
}
Expand Down
15 changes: 13 additions & 2 deletions src/fs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use anyhow::Result;
use std::fs::File;
use std::io::{BufReader, Read};
use std::io::{BufRead, BufReader, Read};
use std::path::{Path, PathBuf};

use anyhow::Result;
use walkdir::{DirEntry, WalkDir};

fn is_not_hidden(entry: &DirEntry) -> bool {
Expand All @@ -21,6 +22,16 @@ pub fn iter_python_files(path: &PathBuf) -> impl Iterator<Item = DirEntry> {
.filter(|entry| entry.path().to_string_lossy().ends_with(".py"))
}

pub fn read_line(path: &Path, row: &usize) -> Result<String> {
let file = File::open(path)?;
let buf_reader = BufReader::new(file);
buf_reader
.lines()
.nth(*row - 1)
.unwrap()
.map_err(|e| e.into())
}

pub fn read_file(path: &Path) -> Result<String> {
let file = File::open(path)?;
let mut buf_reader = BufReader::new(file);
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ pub mod fs;
pub mod linter;
pub mod logging;
pub mod message;
mod settings;
mod visitor;
22 changes: 15 additions & 7 deletions src/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub fn check_path(path: &Path, mode: &cache::Mode) -> Result<Vec<Message>> {
location: check.location,
filename: path.to_string_lossy().to_string(),
})
.filter(|message| !message.is_inline_ignored())
.collect();
cache::set(path, &messages, mode);

Expand Down Expand Up @@ -61,7 +62,7 @@ mod tests {
},
Message {
kind: DuplicateArgumentName,
location: Location::new(5, 9),
location: Location::new(5, 28),
filename: "./resources/test/src/duplicate_argument_name.py".to_string(),
},
Message {
Expand Down Expand Up @@ -110,11 +111,18 @@ mod tests {
&Path::new("./resources/test/src/import_star_usage.py"),
&cache::Mode::None,
)?;
let expected = vec![Message {
kind: ImportStarUsage,
location: Location::new(1, 1),
filename: "./resources/test/src/import_star_usage.py".to_string(),
}];
let expected = vec![
Message {
kind: ImportStarUsage,
location: Location::new(1, 1),
filename: "./resources/test/src/import_star_usage.py".to_string(),
},
Message {
kind: ImportStarUsage,
location: Location::new(2, 1),
filename: "./resources/test/src/import_star_usage.py".to_string(),
},
];
assert_eq!(actual.len(), expected.len());
for i in 1..actual.len() {
assert_eq!(actual[i], expected[i]);
Expand All @@ -131,7 +139,7 @@ mod tests {
)?;
let expected = vec![Message {
kind: LineTooLong,
location: Location::new(3, 80),
location: Location::new(3, 88),
filename: "./resources/test/src/line_too_long.py".to_string(),
}];
assert_eq!(actual.len(), expected.len());
Expand Down
35 changes: 35 additions & 0 deletions src/message.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::fmt;
use std::path::Path;

use colored::Colorize;
use regex::Regex;
use rustpython_parser::ast::Location;
use serde::{Deserialize, Serialize};

use crate::checks::CheckKind;
use crate::fs;

#[derive(Serialize, Deserialize)]
#[serde(remote = "Location")]
Expand All @@ -29,6 +32,38 @@ pub struct Message {
pub filename: String,
}

impl Message {
pub fn is_inline_ignored(&self) -> bool {
match fs::read_line(Path::new(&self.filename), &self.location.row()) {
Ok(line) => {
// https://github.com/PyCQA/flake8/blob/799c71eeb61cf26c7c176aed43e22523e2a6d991/src/flake8/defaults.py#L26
let re = Regex::new(r"(?i)# noqa(?::\s?(?P<codes>([A-Z]+[0-9]+(?:[,\s]+)?)+))?")
.unwrap();
match re.captures(&line) {
Some(caps) => match caps.name("codes") {
Some(codes) => {
let re = Regex::new(r"[,\s]").unwrap();
for code in re
.split(codes.as_str())
.map(|code| code.trim())
.filter(|code| !code.is_empty())
{
if code == self.kind.code() {
return true;
}
}
false
}
None => true,
},
None => false,
}
}
Err(_) => false,
}
}
}

impl fmt::Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
Expand Down
1 change: 1 addition & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub static MAX_LINE_LENGTH: &usize = &88;

0 comments on commit 3b1b53d

Please sign in to comment.