mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:47 +00:00
Represent per-file ignores as a map (#531)
This commit is contained in:
parent
5aa8455258
commit
5797884262
11 changed files with 166 additions and 133 deletions
|
@ -42,7 +42,10 @@ pub fn convert(config: HashMap<String, HashMap<String, Option<String>>>) -> Resu
|
|||
}
|
||||
"per-file-ignores" | "per_file_ignores" => {
|
||||
match parser::parse_files_to_codes_mapping(value.as_ref()) {
|
||||
Ok(per_file_ignores) => options.per_file_ignores = Some(per_file_ignores),
|
||||
Ok(per_file_ignores) => {
|
||||
options.per_file_ignores =
|
||||
Some(parser::collect_per_file_ignores(per_file_ignores))
|
||||
}
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
|
@ -5,7 +6,7 @@ use once_cell::sync::Lazy;
|
|||
use regex::Regex;
|
||||
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::StrCheckCodePair;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
|
||||
static COMMA_SEPARATED_LIST_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[,\s]").unwrap());
|
||||
|
||||
|
@ -70,15 +71,15 @@ impl State {
|
|||
}
|
||||
|
||||
/// Generate the list of `StrCheckCodePair` pairs for the current state.
|
||||
fn parse(&self) -> Vec<StrCheckCodePair> {
|
||||
let mut codes: Vec<StrCheckCodePair> = vec![];
|
||||
fn parse(&self) -> Vec<PatternPrefixPair> {
|
||||
let mut codes: Vec<PatternPrefixPair> = vec![];
|
||||
for code in &self.codes {
|
||||
match CheckCodePrefix::from_str(code) {
|
||||
Ok(code) => {
|
||||
for filename in &self.filenames {
|
||||
codes.push(StrCheckCodePair {
|
||||
codes.push(PatternPrefixPair {
|
||||
pattern: filename.clone(),
|
||||
code: code.clone(),
|
||||
prefix: code.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -127,11 +128,11 @@ fn tokenize_files_to_codes_mapping(value: &str) -> Vec<Token> {
|
|||
/// Parse a 'files-to-codes' mapping, mimicking Flake8's internal logic.
|
||||
///
|
||||
/// See: https://github.com/PyCQA/flake8/blob/7dfe99616fc2f07c0017df2ba5fa884158f3ea8a/src/flake8/utils.py#L45
|
||||
pub fn parse_files_to_codes_mapping(value: &str) -> Result<Vec<StrCheckCodePair>> {
|
||||
pub fn parse_files_to_codes_mapping(value: &str) -> Result<Vec<PatternPrefixPair>> {
|
||||
if value.trim().is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
let mut codes: Vec<StrCheckCodePair> = vec![];
|
||||
let mut codes: Vec<PatternPrefixPair> = vec![];
|
||||
let mut state = State::new();
|
||||
for token in tokenize_files_to_codes_mapping(value) {
|
||||
if matches!(token.token_name, TokenType::Comma | TokenType::Ws) {
|
||||
|
@ -166,12 +167,26 @@ pub fn parse_files_to_codes_mapping(value: &str) -> Result<Vec<StrCheckCodePair>
|
|||
Ok(codes)
|
||||
}
|
||||
|
||||
/// Collect a list of `PatternPrefixPair` structs as a `BTreeMap`.
|
||||
pub fn collect_per_file_ignores(
|
||||
pairs: Vec<PatternPrefixPair>,
|
||||
) -> BTreeMap<String, Vec<CheckCodePrefix>> {
|
||||
let mut per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>> = BTreeMap::new();
|
||||
for pair in pairs {
|
||||
per_file_ignores
|
||||
.entry(pair.pattern)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(pair.prefix);
|
||||
}
|
||||
per_file_ignores
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::StrCheckCodePair;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
|
||||
use crate::parser::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};
|
||||
|
||||
|
@ -232,11 +247,11 @@ mod tests {
|
|||
#[test]
|
||||
fn it_parse_files_to_codes_mapping() -> Result<()> {
|
||||
let actual = parse_files_to_codes_mapping("")?;
|
||||
let expected: Vec<StrCheckCodePair> = vec![];
|
||||
let expected: Vec<PatternPrefixPair> = vec![];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = parse_files_to_codes_mapping(" ")?;
|
||||
let expected: Vec<StrCheckCodePair> = vec![];
|
||||
let expected: Vec<PatternPrefixPair> = vec![];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
// Ex) locust
|
||||
|
@ -248,14 +263,14 @@ mod tests {
|
|||
.strip_prefix("per-file-ignores =")
|
||||
.unwrap(),
|
||||
)?;
|
||||
let expected: Vec<StrCheckCodePair> = vec![
|
||||
StrCheckCodePair {
|
||||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "locust/test/*".to_string(),
|
||||
code: CheckCodePrefix::F841,
|
||||
prefix: CheckCodePrefix::F841,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "examples/*".to_string(),
|
||||
code: CheckCodePrefix::F841,
|
||||
prefix: CheckCodePrefix::F841,
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
@ -268,26 +283,26 @@ mod tests {
|
|||
.strip_prefix("per-file-ignores =")
|
||||
.unwrap(),
|
||||
)?;
|
||||
let expected: Vec<StrCheckCodePair> = vec![
|
||||
StrCheckCodePair {
|
||||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "t/*".to_string(),
|
||||
code: CheckCodePrefix::D,
|
||||
prefix: CheckCodePrefix::D,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "setup.py".to_string(),
|
||||
code: CheckCodePrefix::D,
|
||||
prefix: CheckCodePrefix::D,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "examples/*".to_string(),
|
||||
code: CheckCodePrefix::D,
|
||||
prefix: CheckCodePrefix::D,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "docs/*".to_string(),
|
||||
code: CheckCodePrefix::D,
|
||||
prefix: CheckCodePrefix::D,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "extra/*".to_string(),
|
||||
code: CheckCodePrefix::D,
|
||||
prefix: CheckCodePrefix::D,
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
@ -306,50 +321,50 @@ mod tests {
|
|||
.strip_prefix("per-file-ignores =")
|
||||
.unwrap(),
|
||||
)?;
|
||||
let expected: Vec<StrCheckCodePair> = vec![
|
||||
StrCheckCodePair {
|
||||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::E402,
|
||||
prefix: CheckCodePrefix::E402,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/core/downloader/handlers/http.py".to_string(),
|
||||
code: CheckCodePrefix::F401,
|
||||
prefix: CheckCodePrefix::F401,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/http/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::F401,
|
||||
prefix: CheckCodePrefix::F401,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/linkextractors/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::E402,
|
||||
prefix: CheckCodePrefix::E402,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/linkextractors/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::F401,
|
||||
prefix: CheckCodePrefix::F401,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/selector/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::F401,
|
||||
prefix: CheckCodePrefix::F401,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/spiders/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::E402,
|
||||
prefix: CheckCodePrefix::E402,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/spiders/__init__.py".to_string(),
|
||||
code: CheckCodePrefix::F401,
|
||||
prefix: CheckCodePrefix::F401,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/utils/url.py".to_string(),
|
||||
code: CheckCodePrefix::F403,
|
||||
prefix: CheckCodePrefix::F403,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/utils/url.py".to_string(),
|
||||
code: CheckCodePrefix::F405,
|
||||
prefix: CheckCodePrefix::F405,
|
||||
},
|
||||
StrCheckCodePair {
|
||||
PatternPrefixPair {
|
||||
pattern: "tests/test_loader.py".to_string(),
|
||||
code: CheckCodePrefix::E741,
|
||||
prefix: CheckCodePrefix::E741,
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
|
38
resources/test/fixtures/pyproject.toml
vendored
38
resources/test/fixtures/pyproject.toml
vendored
|
@ -1,13 +1,11 @@
|
|||
[tool.ruff]
|
||||
line-length = 88
|
||||
extend-exclude = [
|
||||
"excluded.py",
|
||||
"migrations",
|
||||
"directory/also_excluded.py",
|
||||
]
|
||||
per-file-ignores = [
|
||||
"__init__.py:F401",
|
||||
"excluded.py",
|
||||
"migrations",
|
||||
"directory/also_excluded.py",
|
||||
]
|
||||
per-file-ignores = { "__init__.py" = ["F401"] }
|
||||
|
||||
[tool.ruff.flake8-quotes]
|
||||
inline-quotes = "single"
|
||||
|
@ -17,22 +15,22 @@ avoid-escape = true
|
|||
|
||||
[tool.ruff.pep8-naming]
|
||||
ignore-names = [
|
||||
"setUp",
|
||||
"tearDown",
|
||||
"setUpClass",
|
||||
"tearDownClass",
|
||||
"setUpModule",
|
||||
"tearDownModule",
|
||||
"asyncSetUp",
|
||||
"asyncTearDown",
|
||||
"setUpTestData",
|
||||
"failureException",
|
||||
"longMessage",
|
||||
"maxDiff",
|
||||
"setUp",
|
||||
"tearDown",
|
||||
"setUpClass",
|
||||
"tearDownClass",
|
||||
"setUpModule",
|
||||
"tearDownModule",
|
||||
"asyncSetUp",
|
||||
"asyncTearDown",
|
||||
"setUpTestData",
|
||||
"failureException",
|
||||
"longMessage",
|
||||
"maxDiff",
|
||||
]
|
||||
classmethod-decorators = [
|
||||
"classmethod",
|
||||
"classmethod",
|
||||
]
|
||||
staticmethod-decorators = [
|
||||
"staticmethod",
|
||||
"staticmethod",
|
||||
]
|
||||
|
|
19
src/cli.rs
19
src/cli.rs
|
@ -1,3 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -8,8 +9,8 @@ use regex::Regex;
|
|||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::printer::SerializationFormat;
|
||||
use crate::settings::configuration::Configuration;
|
||||
use crate::settings::types::PatternPrefixPair;
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::settings::types::StrCheckCodePair;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(author, about = "ruff: An extremely fast Python linter.")]
|
||||
|
@ -61,7 +62,7 @@ pub struct Cli {
|
|||
pub extend_exclude: Vec<String>,
|
||||
/// List of mappings from file pattern to code to exclude
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub per_file_ignores: Vec<StrCheckCodePair>,
|
||||
pub per_file_ignores: Vec<PatternPrefixPair>,
|
||||
/// Output serialization format for error messages.
|
||||
#[arg(long, value_enum, default_value_t=SerializationFormat::Text)]
|
||||
pub format: SerializationFormat,
|
||||
|
@ -143,3 +144,17 @@ pub fn warn_on(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect a list of `PatternPrefixPair` structs as a `BTreeMap`.
|
||||
pub fn collect_per_file_ignores(
|
||||
pairs: Vec<PatternPrefixPair>,
|
||||
) -> BTreeMap<String, Vec<CheckCodePrefix>> {
|
||||
let mut per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>> = BTreeMap::new();
|
||||
for pair in pairs {
|
||||
per_file_ignores
|
||||
.entry(pair.pattern)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(pair.prefix);
|
||||
}
|
||||
per_file_ignores
|
||||
}
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -1,3 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitCode;
|
||||
|
@ -17,7 +18,8 @@ use walkdir::DirEntry;
|
|||
use ruff::cache;
|
||||
use ruff::checks::CheckCode;
|
||||
use ruff::checks::CheckKind;
|
||||
use ruff::cli::{warn_on, Cli, Warnable};
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::cli::{collect_per_file_ignores, warn_on, Cli, Warnable};
|
||||
use ruff::fs::iter_python_files;
|
||||
use ruff::linter::add_noqa_to_path;
|
||||
use ruff::linter::autoformat_path;
|
||||
|
@ -27,7 +29,7 @@ use ruff::message::Message;
|
|||
use ruff::printer::{Printer, SerializationFormat};
|
||||
use ruff::settings::configuration::Configuration;
|
||||
use ruff::settings::pyproject;
|
||||
use ruff::settings::types::{FilePattern, PerFileIgnore};
|
||||
use ruff::settings::types::FilePattern;
|
||||
use ruff::settings::user::UserConfiguration;
|
||||
use ruff::settings::Settings;
|
||||
use ruff::tell_user;
|
||||
|
@ -255,11 +257,8 @@ fn inner_main() -> Result<ExitCode> {
|
|||
.iter()
|
||||
.map(|path| FilePattern::from_user(path, &project_root))
|
||||
.collect();
|
||||
let per_file_ignores: Vec<PerFileIgnore> = cli
|
||||
.per_file_ignores
|
||||
.into_iter()
|
||||
.map(|pair| PerFileIgnore::new(pair, &project_root))
|
||||
.collect();
|
||||
let per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>> =
|
||||
collect_per_file_ignores(cli.per_file_ignores);
|
||||
|
||||
let mut configuration = Configuration::from_pyproject(&pyproject, &project_root)?;
|
||||
if !exclude.is_empty() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! User-provided program settings, taking into account pyproject.toml and command-line options.
|
||||
//! Structure mirrors the user-facing representation of the various parameters.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
|
@ -9,7 +10,7 @@ use regex::Regex;
|
|||
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::settings::pyproject::load_options;
|
||||
use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion};
|
||||
use crate::settings::types::{FilePattern, PythonVersion};
|
||||
use crate::{flake8_quotes, pep8_naming};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -21,7 +22,7 @@ pub struct Configuration {
|
|||
pub extend_select: Vec<CheckCodePrefix>,
|
||||
pub ignore: Vec<CheckCodePrefix>,
|
||||
pub line_length: usize,
|
||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||
pub per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>>,
|
||||
pub select: Vec<CheckCodePrefix>,
|
||||
pub target_version: PythonVersion,
|
||||
// Plugins
|
||||
|
@ -91,12 +92,7 @@ impl Configuration {
|
|||
extend_select: options.extend_select.unwrap_or_default(),
|
||||
ignore: options.ignore.unwrap_or_default(),
|
||||
line_length: options.line_length.unwrap_or(88),
|
||||
per_file_ignores: options
|
||||
.per_file_ignores
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|pair| PerFileIgnore::new(pair, project_root))
|
||||
.collect(),
|
||||
per_file_ignores: options.per_file_ignores.unwrap_or_default(),
|
||||
// Plugins
|
||||
flake8_quotes: options
|
||||
.flake8_quotes
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Effective program settings, taking into account pyproject.toml and command-line options.
|
||||
//! Structure is optimized for internal usage, as opposed to external visibility or parsing.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use regex::Regex;
|
||||
|
@ -47,7 +47,7 @@ impl Settings {
|
|||
flake8_quotes: config.flake8_quotes,
|
||||
line_length: config.line_length,
|
||||
pep8_naming: config.pep8_naming,
|
||||
per_file_ignores: config.per_file_ignores,
|
||||
per_file_ignores: resolve_per_file_ignores(&config.per_file_ignores),
|
||||
target_version: config.target_version,
|
||||
}
|
||||
}
|
||||
|
@ -56,10 +56,10 @@ impl Settings {
|
|||
Self {
|
||||
dummy_variable_rgx: Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$").unwrap(),
|
||||
enabled: BTreeSet::from([check_code]),
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
exclude: Default::default(),
|
||||
extend_exclude: Default::default(),
|
||||
line_length: 88,
|
||||
per_file_ignores: vec![],
|
||||
per_file_ignores: Default::default(),
|
||||
target_version: PythonVersion::Py310,
|
||||
flake8_quotes: Default::default(),
|
||||
pep8_naming: Default::default(),
|
||||
|
@ -70,10 +70,10 @@ impl Settings {
|
|||
Self {
|
||||
dummy_variable_rgx: Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$").unwrap(),
|
||||
enabled: BTreeSet::from_iter(check_codes),
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
exclude: Default::default(),
|
||||
extend_exclude: Default::default(),
|
||||
line_length: 88,
|
||||
per_file_ignores: vec![],
|
||||
per_file_ignores: Default::default(),
|
||||
target_version: PythonVersion::Py310,
|
||||
flake8_quotes: Default::default(),
|
||||
pep8_naming: Default::default(),
|
||||
|
@ -136,6 +136,15 @@ fn resolve_codes(
|
|||
codes
|
||||
}
|
||||
|
||||
fn resolve_per_file_ignores(
|
||||
per_file_ignores: &BTreeMap<String, Vec<CheckCodePrefix>>,
|
||||
) -> Vec<PerFileIgnore> {
|
||||
per_file_ignores
|
||||
.iter()
|
||||
.map(|(pattern, prefixes)| PerFileIgnore::new(pattern, prefixes, &None))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeSet;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
//! Options that the user can provide via pyproject.toml.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::settings::types::{PythonVersion, StrCheckCodePair};
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::{flake8_quotes, pep8_naming};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
|
@ -16,7 +18,7 @@ pub struct Options {
|
|||
pub extend_select: Option<Vec<CheckCodePrefix>>,
|
||||
pub ignore: Option<Vec<CheckCodePrefix>>,
|
||||
pub extend_ignore: Option<Vec<CheckCodePrefix>>,
|
||||
pub per_file_ignores: Option<Vec<StrCheckCodePair>>,
|
||||
pub per_file_ignores: Option<BTreeMap<String, Vec<CheckCodePrefix>>>,
|
||||
pub dummy_variable_rgx: Option<String>,
|
||||
pub target_version: Option<PythonVersion>,
|
||||
// Plugins
|
||||
|
|
|
@ -96,6 +96,7 @@ pub fn load_options(pyproject: &Option<PathBuf>) -> Result<Options> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
use std::env::current_dir;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
@ -107,7 +108,7 @@ mod tests {
|
|||
use crate::settings::pyproject::{
|
||||
find_project_root, find_pyproject_toml, parse_pyproject_toml, Options, Pyproject, Tools,
|
||||
};
|
||||
use crate::settings::types::StrCheckCodePair;
|
||||
use crate::settings::types::PatternPrefixPair;
|
||||
use crate::{flake8_quotes, pep8_naming};
|
||||
|
||||
#[test]
|
||||
|
@ -319,10 +320,10 @@ other-attribute = 1
|
|||
extend_select: None,
|
||||
ignore: None,
|
||||
extend_ignore: None,
|
||||
per_file_ignores: Some(vec![StrCheckCodePair {
|
||||
pattern: "__init__.py".to_string(),
|
||||
code: CheckCodePrefix::F401
|
||||
}]),
|
||||
per_file_ignores: Some(BTreeMap::from([(
|
||||
"__init__.py".to_string(),
|
||||
vec![CheckCodePrefix::F401]
|
||||
),])),
|
||||
dummy_variable_rgx: None,
|
||||
target_version: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
|
@ -357,21 +358,21 @@ other-attribute = 1
|
|||
|
||||
#[test]
|
||||
fn str_check_code_pair_strings() {
|
||||
let result = StrCheckCodePair::from_str("foo:E501");
|
||||
let result = PatternPrefixPair::from_str("foo:E501");
|
||||
assert!(result.is_ok());
|
||||
let result = StrCheckCodePair::from_str("foo: E501");
|
||||
let result = PatternPrefixPair::from_str("foo: E501");
|
||||
assert!(result.is_ok());
|
||||
let result = StrCheckCodePair::from_str("E501:foo");
|
||||
let result = PatternPrefixPair::from_str("E501:foo");
|
||||
assert!(result.is_err());
|
||||
let result = StrCheckCodePair::from_str("E501");
|
||||
let result = PatternPrefixPair::from_str("E501");
|
||||
assert!(result.is_err());
|
||||
let result = StrCheckCodePair::from_str("foo");
|
||||
let result = PatternPrefixPair::from_str("foo");
|
||||
assert!(result.is_err());
|
||||
let result = StrCheckCodePair::from_str("foo:E501:E402");
|
||||
let result = PatternPrefixPair::from_str("foo:E501:E402");
|
||||
assert!(result.is_err());
|
||||
let result = StrCheckCodePair::from_str("**/bar:E501");
|
||||
let result = PatternPrefixPair::from_str("**/bar:E501");
|
||||
assert!(result.is_ok());
|
||||
let result = StrCheckCodePair::from_str("bar:E502");
|
||||
let result = PatternPrefixPair::from_str("bar:E502");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::str::FromStr;
|
|||
|
||||
use anyhow::{anyhow, Result};
|
||||
use glob::Pattern;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::checks::CheckCode;
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
|
@ -75,24 +75,28 @@ pub struct PerFileIgnore {
|
|||
}
|
||||
|
||||
impl PerFileIgnore {
|
||||
pub fn new(user_in: StrCheckCodePair, project_root: &Option<PathBuf>) -> Self {
|
||||
let pattern = FilePattern::from_user(user_in.pattern.as_str(), project_root);
|
||||
let codes = BTreeSet::from_iter(user_in.code.codes());
|
||||
pub fn new(
|
||||
pattern: &str,
|
||||
prefixes: &[CheckCodePrefix],
|
||||
project_root: &Option<PathBuf>,
|
||||
) -> Self {
|
||||
let pattern = FilePattern::from_user(pattern, project_root);
|
||||
let codes = BTreeSet::from_iter(prefixes.iter().flat_map(|prefix| prefix.codes()));
|
||||
Self { pattern, codes }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct StrCheckCodePair {
|
||||
pub struct PatternPrefixPair {
|
||||
pub pattern: String,
|
||||
pub code: CheckCodePrefix,
|
||||
pub prefix: CheckCodePrefix,
|
||||
}
|
||||
|
||||
impl StrCheckCodePair {
|
||||
impl PatternPrefixPair {
|
||||
const EXPECTED_PATTERN: &'static str = "<FilePattern>:<CheckCode> pattern";
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for StrCheckCodePair {
|
||||
impl<'de> Deserialize<'de> for PatternPrefixPair {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
@ -107,17 +111,7 @@ impl<'de> Deserialize<'de> for StrCheckCodePair {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serialize for StrCheckCodePair {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let as_str = format!("{}:{}", self.pattern, self.code.as_ref());
|
||||
serializer.serialize_str(&as_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for StrCheckCodePair {
|
||||
impl FromStr for PatternPrefixPair {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
|
@ -128,8 +122,8 @@ impl FromStr for StrCheckCodePair {
|
|||
}
|
||||
(tokens[0].trim(), tokens[1].trim())
|
||||
};
|
||||
let code = CheckCodePrefix::from_str(code_string)?;
|
||||
let pattern = pattern_str.into();
|
||||
Ok(Self { pattern, code })
|
||||
let prefix = CheckCodePrefix::from_str(code_string)?;
|
||||
Ok(Self { pattern, prefix })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
//! Structs to render user-facing settings.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion};
|
||||
use crate::settings::types::{FilePattern, PythonVersion};
|
||||
use crate::{flake8_quotes, pep8_naming, Configuration};
|
||||
|
||||
/// Struct to render user-facing exclusion patterns.
|
||||
|
@ -41,7 +42,7 @@ pub struct UserConfiguration {
|
|||
pub extend_select: Vec<CheckCodePrefix>,
|
||||
pub ignore: Vec<CheckCodePrefix>,
|
||||
pub line_length: usize,
|
||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||
pub per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>>,
|
||||
pub select: Vec<CheckCodePrefix>,
|
||||
pub target_version: PythonVersion,
|
||||
// Plugins
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue