diff --git a/LICENSE b/LICENSE index 875b07cf86..d20cfe5133 100644 --- a/LICENSE +++ b/LICENSE @@ -218,6 +218,31 @@ are: SOFTWARE. """ +- flake8-tidy-imports, licensed as follows: + """ + MIT License + + Copyright (c) 2017 Adam Johnson + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + - flake8-print, licensed as follows: """ MIT License diff --git a/README.md b/README.md index 2eb514f4cf..13e0bb8827 100644 --- a/README.md +++ b/README.md @@ -548,6 +548,14 @@ For more, see [flake8-builtins](https://pypi.org/project/flake8-builtins/2.0.1/) | A002 | BuiltinArgumentShadowing | Argument `...` is shadowing a python builtin | | | A003 | BuiltinAttributeShadowing | Class attribute `...` is shadowing a python builtin | | +### flake8-tidy-imports + +For more, see [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/4.8.0/) on PyPI. + +| Code | Name | Message | Fix | +| ---- | ---- | ------- | --- | +| I252 | BannedRelativeImport | Relative imports are banned | | + ### flake8-print For more, see [flake8-print](https://pypi.org/project/flake8-print/5.0.0/) on PyPI. diff --git a/flake8_to_ruff/src/converter.rs b/flake8_to_ruff/src/converter.rs index 829f2139b3..7aba8fb79b 100644 --- a/flake8_to_ruff/src/converter.rs +++ b/flake8_to_ruff/src/converter.rs @@ -3,9 +3,10 @@ use std::collections::{BTreeSet, HashMap}; use anyhow::Result; use ruff::checks_gen::CheckCodePrefix; use ruff::flake8_quotes::settings::Quote; +use ruff::flake8_tidy_imports::settings::Strictness; use ruff::settings::options::Options; use ruff::settings::pyproject::Pyproject; -use ruff::{flake8_annotations, flake8_bugbear, flake8_quotes, pep8_naming}; +use ruff::{flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, pep8_naming}; use crate::plugin::Plugin; use crate::{parser, plugin}; @@ -71,6 +72,7 @@ pub fn convert( let mut flake8_annotations: flake8_annotations::settings::Options = Default::default(); let mut flake8_bugbear: flake8_bugbear::settings::Options = Default::default(); let mut flake8_quotes: flake8_quotes::settings::Options = Default::default(); + let mut flake8_tidy_imports: flake8_tidy_imports::settings::Options = Default::default(); let mut pep8_naming: pep8_naming::settings::Options = Default::default(); for (key, value) in flake8 { if let Some(value) = value { @@ -172,6 +174,14 @@ pub fn convert( pep8_naming.staticmethod_decorators = Some(parser::parse_strings(value.as_ref())); } + // flake8-tidy-imports + "ban-relative-imports" | "ban_relative_imports" => match value.trim() { + "true" => flake8_tidy_imports.ban_relative_imports = Some(Strictness::All), + "parents" => { + flake8_tidy_imports.ban_relative_imports = Some(Strictness::Parents) + } + _ => eprintln!("Unexpected '{key}' value: {value}"), + }, // flake8-docstrings "docstring-convention" => { // No-op (handled above). @@ -194,6 +204,9 @@ pub fn convert( if flake8_quotes != Default::default() { options.flake8_quotes = Some(flake8_quotes); } + if flake8_tidy_imports != Default::default() { + options.flake8_tidy_imports = Some(flake8_tidy_imports); + } if pep8_naming != Default::default() { options.pep8_naming = Some(pep8_naming); } @@ -238,6 +251,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -272,6 +286,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -306,6 +321,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -340,6 +356,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -379,6 +396,7 @@ mod tests { docstring_quotes: None, avoid_escape: None, }), + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -451,6 +469,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); @@ -491,6 +510,7 @@ mod tests { docstring_quotes: None, avoid_escape: None, }), + flake8_tidy_imports: None, isort: None, pep8_naming: None, }); diff --git a/flake8_to_ruff/src/plugin.rs b/flake8_to_ruff/src/plugin.rs index 5700125c26..519a675724 100644 --- a/flake8_to_ruff/src/plugin.rs +++ b/flake8_to_ruff/src/plugin.rs @@ -11,6 +11,7 @@ pub enum Plugin { Flake8Builtins, Flake8Comprehensions, Flake8Docstrings, + Flake8TidyImports, Flake8Print, Flake8Quotes, Flake8Annotations, @@ -28,6 +29,7 @@ impl FromStr for Plugin { "flake8-builtins" => Ok(Plugin::Flake8Builtins), "flake8-comprehensions" => Ok(Plugin::Flake8Comprehensions), "flake8-docstrings" => Ok(Plugin::Flake8Docstrings), + "flake8-tidy-imports" => Ok(Plugin::Flake8TidyImports), "flake8-print" => Ok(Plugin::Flake8Print), "flake8-quotes" => Ok(Plugin::Flake8Quotes), "flake8-annotations" => Ok(Plugin::Flake8Annotations), @@ -46,6 +48,7 @@ impl Plugin { Plugin::Flake8Builtins => CheckCodePrefix::A, Plugin::Flake8Comprehensions => CheckCodePrefix::C, Plugin::Flake8Docstrings => CheckCodePrefix::D, + Plugin::Flake8TidyImports => CheckCodePrefix::I25, Plugin::Flake8Print => CheckCodePrefix::T, Plugin::Flake8Quotes => CheckCodePrefix::Q, Plugin::Flake8Annotations => CheckCodePrefix::ANN, @@ -76,6 +79,7 @@ impl Plugin { // Default to PEP8. DocstringConvention::PEP8.select() } + Plugin::Flake8TidyImports => vec![CheckCodePrefix::I25], Plugin::Flake8Print => vec![CheckCodePrefix::T], Plugin::Flake8Quotes => vec![CheckCodePrefix::Q], Plugin::Flake8Annotations => vec![CheckCodePrefix::ANN], @@ -315,6 +319,13 @@ pub fn infer_plugins_from_options(flake8: &HashMap>) -> V "allow-star-arg-any" | "allow_star_arg_any" => { plugins.insert(Plugin::Flake8Annotations); } + // flake8-tidy-imports + "ban-relative-imports" | "ban_relative_imports" => { + plugins.insert(Plugin::Flake8TidyImports); + } + "banned-modules" | "banned_modules" => { + plugins.insert(Plugin::Flake8TidyImports); + } // pep8-naming "ignore-names" | "ignore_names" => { plugins.insert(Plugin::PEP8Naming); @@ -342,6 +353,7 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet) -> Vec "flake8-builtins", CheckCategory::Flake8Bugbear => "flake8-bugbear", CheckCategory::Flake8Comprehensions => "flake8-comprehensions", + CheckCategory::Flake8TidyImports => "flake8-tidy-imports", CheckCategory::Flake8Print => "flake8-print", CheckCategory::Flake8Quotes => "flake8-quotes", CheckCategory::Flake8Annotations => "flake8-annotations", @@ -296,6 +301,9 @@ impl CheckCategory { CheckCategory::Flake8Comprehensions => { Some("https://pypi.org/project/flake8-comprehensions/3.10.1/") } + CheckCategory::Flake8TidyImports => { + Some("https://pypi.org/project/flake8-tidy-imports/4.8.0/") + } CheckCategory::Flake8Print => Some("https://pypi.org/project/flake8-print/5.0.0/"), CheckCategory::Flake8Quotes => Some("https://pypi.org/project/flake8-quotes/3.3.1/"), CheckCategory::Flake8Annotations => { @@ -423,6 +431,8 @@ pub enum CheckKind { UnnecessarySubscriptReversal(String), UnnecessaryComprehension(String), UnnecessaryMap(String), + // flake8-tidy-imports + BannedRelativeImport(Strictness), // flake8-print PrintFound, PPrintFound, @@ -682,6 +692,8 @@ impl CheckCode { } CheckCode::C416 => CheckKind::UnnecessaryComprehension("(list|set)".to_string()), CheckCode::C417 => CheckKind::UnnecessaryMap("(list|set|dict)".to_string()), + // flake8-tidy-imports + CheckCode::I252 => CheckKind::BannedRelativeImport(Strictness::All), // flake8-print CheckCode::T201 => CheckKind::PrintFound, CheckCode::T203 => CheckKind::PPrintFound, @@ -913,6 +925,7 @@ impl CheckCode { CheckCode::C415 => CheckCategory::Flake8Comprehensions, CheckCode::C416 => CheckCategory::Flake8Comprehensions, CheckCode::C417 => CheckCategory::Flake8Comprehensions, + CheckCode::I252 => CheckCategory::Flake8TidyImports, CheckCode::T201 => CheckCategory::Flake8Print, CheckCode::T203 => CheckCategory::Flake8Print, CheckCode::Q000 => CheckCategory::Flake8Quotes, @@ -1122,6 +1135,8 @@ impl CheckKind { CheckKind::UnnecessarySubscriptReversal(_) => &CheckCode::C415, CheckKind::UnnecessaryComprehension(..) => &CheckCode::C416, CheckKind::UnnecessaryMap(_) => &CheckCode::C417, + // flake8-tidy-imports + CheckKind::BannedRelativeImport(_) => &CheckCode::I252, // flake8-print CheckKind::PrintFound => &CheckCode::T201, CheckKind::PPrintFound => &CheckCode::T203, @@ -1574,6 +1589,13 @@ impl CheckKind { format!("Unnecessary `map` usage (rewrite using a `{obj_type}` comprehension)") } } + // flake8-tidy-imports + CheckKind::BannedRelativeImport(strictness) => match strictness { + Strictness::Parents => { + "Relative imports from parent modules are banned".to_string() + } + Strictness::All => "Relative imports are banned".to_string(), + }, // flake8-print CheckKind::PrintFound => "`print` found".to_string(), CheckKind::PPrintFound => "`pprint` found".to_string(), diff --git a/src/checks_gen.rs b/src/checks_gen.rs index b423fab737..9fddec318c 100644 --- a/src/checks_gen.rs +++ b/src/checks_gen.rs @@ -215,6 +215,9 @@ pub enum CheckCodePrefix { I0, I00, I001, + I2, + I25, + I252, M, M0, M00, @@ -925,10 +928,13 @@ impl CheckCodePrefix { CheckCodePrefix::F9 => vec![CheckCode::F901], CheckCodePrefix::F90 => vec![CheckCode::F901], CheckCodePrefix::F901 => vec![CheckCode::F901], - CheckCodePrefix::I => vec![CheckCode::I001], + CheckCodePrefix::I => vec![CheckCode::I252, CheckCode::I001], CheckCodePrefix::I0 => vec![CheckCode::I001], CheckCodePrefix::I00 => vec![CheckCode::I001], CheckCodePrefix::I001 => vec![CheckCode::I001], + CheckCodePrefix::I2 => vec![CheckCode::I252], + CheckCodePrefix::I25 => vec![CheckCode::I252], + CheckCodePrefix::I252 => vec![CheckCode::I252], CheckCodePrefix::M => vec![CheckCode::M001], CheckCodePrefix::M0 => vec![CheckCode::M001], CheckCodePrefix::M00 => vec![CheckCode::M001], @@ -1372,6 +1378,9 @@ impl CheckCodePrefix { CheckCodePrefix::I0 => PrefixSpecificity::Hundreds, CheckCodePrefix::I00 => PrefixSpecificity::Tens, CheckCodePrefix::I001 => PrefixSpecificity::Explicit, + CheckCodePrefix::I2 => PrefixSpecificity::Hundreds, + CheckCodePrefix::I25 => PrefixSpecificity::Tens, + CheckCodePrefix::I252 => PrefixSpecificity::Explicit, CheckCodePrefix::M => PrefixSpecificity::Category, CheckCodePrefix::M0 => PrefixSpecificity::Hundreds, CheckCodePrefix::M00 => PrefixSpecificity::Tens, diff --git a/src/flake8_quotes/settings.rs b/src/flake8_quotes/settings.rs index 9263541268..199d0fc9db 100644 --- a/src/flake8_quotes/settings.rs +++ b/src/flake8_quotes/settings.rs @@ -1,4 +1,4 @@ -//! Settings for the `flake-quotes` plugin. +//! Settings for the `flake8-quotes` plugin. use serde::{Deserialize, Serialize}; diff --git a/src/flake8_tidy_imports/checks.rs b/src/flake8_tidy_imports/checks.rs new file mode 100644 index 0000000000..177a92ff9d --- /dev/null +++ b/src/flake8_tidy_imports/checks.rs @@ -0,0 +1,26 @@ +use rustpython_ast::Stmt; + +use crate::ast::types::Range; +use crate::checks::{Check, CheckKind}; +use crate::flake8_tidy_imports::settings::Strictness; + +pub fn banned_relative_import( + stmt: &Stmt, + level: Option<&usize>, + strictness: &Strictness, +) -> Option { + if let Some(level) = level { + if level + > &match strictness { + Strictness::All => 0, + Strictness::Parents => 1, + } + { + return Some(Check::new( + CheckKind::BannedRelativeImport(strictness.clone()), + Range::from_located(stmt), + )); + } + } + None +} diff --git a/src/flake8_tidy_imports/mod.rs b/src/flake8_tidy_imports/mod.rs new file mode 100644 index 0000000000..c49668a024 --- /dev/null +++ b/src/flake8_tidy_imports/mod.rs @@ -0,0 +1,49 @@ +pub mod checks; +pub mod settings; + +#[cfg(test)] +mod tests { + use std::path::Path; + + use anyhow::Result; + + use crate::autofix::fixer; + use crate::checks::CheckCode; + use crate::flake8_tidy_imports::settings::Strictness; + use crate::linter::test_path; + use crate::{flake8_tidy_imports, Settings}; + + #[test] + fn ban_parent_imports() -> Result<()> { + let mut checks = test_path( + Path::new("./resources/test/fixtures/I252.py"), + &Settings { + flake8_tidy_imports: flake8_tidy_imports::settings::Settings { + ban_relative_imports: Strictness::Parents, + }, + ..Settings::for_rules(vec![CheckCode::I252]) + }, + &fixer::Mode::Generate, + )?; + checks.sort_by_key(|check| check.location); + insta::assert_yaml_snapshot!(checks); + Ok(()) + } + + #[test] + fn ban_all_imports() -> Result<()> { + let mut checks = test_path( + Path::new("./resources/test/fixtures/I252.py"), + &Settings { + flake8_tidy_imports: flake8_tidy_imports::settings::Settings { + ban_relative_imports: Strictness::All, + }, + ..Settings::for_rules(vec![CheckCode::I252]) + }, + &fixer::Mode::Generate, + )?; + checks.sort_by_key(|check| check.location); + insta::assert_yaml_snapshot!(checks); + Ok(()) + } +} diff --git a/src/flake8_tidy_imports/settings.rs b/src/flake8_tidy_imports/settings.rs new file mode 100644 index 0000000000..3792f98592 --- /dev/null +++ b/src/flake8_tidy_imports/settings.rs @@ -0,0 +1,37 @@ +//! Settings for the `flake8-tidy-imports` plugin. + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] +pub enum Strictness { + Parents, + All, +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] +pub struct Options { + pub ban_relative_imports: Option, +} + +#[derive(Debug, Hash)] +pub struct Settings { + pub ban_relative_imports: Strictness, +} + +impl Settings { + pub fn from_options(options: Options) -> Self { + Self { + ban_relative_imports: options.ban_relative_imports.unwrap_or(Strictness::Parents), + } + } +} + +impl Default for Settings { + fn default() -> Self { + Self { + ban_relative_imports: Strictness::Parents, + } + } +} diff --git a/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_all_imports.snap b/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_all_imports.snap new file mode 100644 index 0000000000..3981a91d16 --- /dev/null +++ b/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_all_imports.snap @@ -0,0 +1,59 @@ +--- +source: src/flake8_tidy_imports/mod.rs +expression: checks +--- +- kind: + BannedRelativeImport: all + location: + row: 1 + column: 0 + end_location: + row: 1 + column: 21 + fix: ~ +- kind: + BannedRelativeImport: all + location: + row: 2 + column: 0 + end_location: + row: 2 + column: 28 + fix: ~ +- kind: + BannedRelativeImport: all + location: + row: 4 + column: 0 + end_location: + row: 4 + column: 21 + fix: ~ +- kind: + BannedRelativeImport: all + location: + row: 5 + column: 0 + end_location: + row: 5 + column: 28 + fix: ~ +- kind: + BannedRelativeImport: all + location: + row: 7 + column: 0 + end_location: + row: 7 + column: 27 + fix: ~ +- kind: + BannedRelativeImport: all + location: + row: 8 + column: 0 + end_location: + row: 8 + column: 34 + fix: ~ + diff --git a/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_parent_imports.snap b/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_parent_imports.snap new file mode 100644 index 0000000000..39c606af9f --- /dev/null +++ b/src/flake8_tidy_imports/snapshots/ruff__flake8_tidy_imports__tests__ban_parent_imports.snap @@ -0,0 +1,41 @@ +--- +source: src/flake8_tidy_imports/mod.rs +expression: checks +--- +- kind: + BannedRelativeImport: parents + location: + row: 4 + column: 0 + end_location: + row: 4 + column: 21 + fix: ~ +- kind: + BannedRelativeImport: parents + location: + row: 5 + column: 0 + end_location: + row: 5 + column: 28 + fix: ~ +- kind: + BannedRelativeImport: parents + location: + row: 7 + column: 0 + end_location: + row: 7 + column: 27 + fix: ~ +- kind: + BannedRelativeImport: parents + location: + row: 8 + column: 0 + end_location: + row: 8 + column: 34 + fix: ~ + diff --git a/src/lib.rs b/src/lib.rs index f5ba90d896..0c974c72ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ mod flake8_builtins; mod flake8_comprehensions; mod flake8_print; pub mod flake8_quotes; +pub mod flake8_tidy_imports; pub mod fs; mod isort; mod lex; diff --git a/src/settings/configuration.rs b/src/settings/configuration.rs index f8da430998..906092d6c7 100644 --- a/src/settings/configuration.rs +++ b/src/settings/configuration.rs @@ -12,7 +12,9 @@ use regex::Regex; use crate::checks_gen::CheckCodePrefix; use crate::settings::pyproject::load_options; use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion}; -use crate::{flake8_annotations, flake8_bugbear, flake8_quotes, fs, isort, pep8_naming}; +use crate::{ + flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, fs, isort, pep8_naming, +}; #[derive(Debug)] pub struct Configuration { @@ -32,6 +34,7 @@ pub struct Configuration { pub flake8_annotations: flake8_annotations::settings::Settings, pub flake8_bugbear: flake8_bugbear::settings::Settings, pub flake8_quotes: flake8_quotes::settings::Settings, + pub flake8_tidy_imports: flake8_tidy_imports::settings::Settings, pub isort: isort::settings::Settings, pub pep8_naming: pep8_naming::settings::Settings, } @@ -142,6 +145,10 @@ impl Configuration { .flake8_quotes .map(flake8_quotes::settings::Settings::from_options) .unwrap_or_default(), + flake8_tidy_imports: options + .flake8_tidy_imports + .map(flake8_tidy_imports::settings::Settings::from_options) + .unwrap_or_default(), isort: options .isort .map(isort::settings::Settings::from_options) diff --git a/src/settings/mod.rs b/src/settings/mod.rs index b1f91b11cb..d64e93f56b 100644 --- a/src/settings/mod.rs +++ b/src/settings/mod.rs @@ -13,7 +13,9 @@ use crate::checks::CheckCode; use crate::checks_gen::{CheckCodePrefix, PrefixSpecificity}; use crate::settings::configuration::Configuration; use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion}; -use crate::{flake8_annotations, flake8_bugbear, flake8_quotes, isort, pep8_naming}; +use crate::{ + flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, isort, pep8_naming, +}; pub mod configuration; pub mod options; @@ -35,6 +37,7 @@ pub struct Settings { pub flake8_annotations: flake8_annotations::settings::Settings, pub flake8_bugbear: flake8_bugbear::settings::Settings, pub flake8_quotes: flake8_quotes::settings::Settings, + pub flake8_tidy_imports: flake8_tidy_imports::settings::Settings, pub isort: isort::settings::Settings, pub pep8_naming: pep8_naming::settings::Settings, } @@ -54,6 +57,7 @@ impl Settings { flake8_annotations: config.flake8_annotations, flake8_bugbear: config.flake8_bugbear, flake8_quotes: config.flake8_quotes, + flake8_tidy_imports: config.flake8_tidy_imports, isort: config.isort, line_length: config.line_length, pep8_naming: config.pep8_naming, @@ -76,6 +80,7 @@ impl Settings { flake8_annotations: Default::default(), flake8_bugbear: Default::default(), flake8_quotes: Default::default(), + flake8_tidy_imports: Default::default(), isort: Default::default(), pep8_naming: Default::default(), } @@ -94,6 +99,7 @@ impl Settings { flake8_annotations: Default::default(), flake8_bugbear: Default::default(), flake8_quotes: Default::default(), + flake8_tidy_imports: Default::default(), isort: Default::default(), pep8_naming: Default::default(), } diff --git a/src/settings/options.rs b/src/settings/options.rs index 4a6e17711e..574e0d7e6a 100644 --- a/src/settings/options.rs +++ b/src/settings/options.rs @@ -5,7 +5,9 @@ use serde::{Deserialize, Serialize}; use crate::checks_gen::CheckCodePrefix; use crate::settings::types::PythonVersion; -use crate::{flake8_annotations, flake8_bugbear, flake8_quotes, isort, pep8_naming}; +use crate::{ + flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, isort, pep8_naming, +}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] @@ -25,6 +27,7 @@ pub struct Options { pub flake8_annotations: Option, pub flake8_bugbear: Option, pub flake8_quotes: Option, + pub flake8_tidy_imports: Option, pub isort: Option, pub pep8_naming: Option, // Tables are required to go last. diff --git a/src/settings/pyproject.rs b/src/settings/pyproject.rs index effd349133..7b11f75549 100644 --- a/src/settings/pyproject.rs +++ b/src/settings/pyproject.rs @@ -105,11 +105,12 @@ mod tests { use crate::checks_gen::CheckCodePrefix; use crate::flake8_quotes::settings::Quote; + use crate::flake8_tidy_imports::settings::Strictness; use crate::settings::pyproject::{ find_project_root, find_pyproject_toml, parse_pyproject_toml, Options, Pyproject, Tools, }; use crate::settings::types::PatternPrefixPair; - use crate::{flake8_bugbear, flake8_quotes, pep8_naming}; + use crate::{flake8_bugbear, flake8_quotes, flake8_tidy_imports, pep8_naming}; #[test] fn deserialize() -> Result<()> { @@ -148,6 +149,7 @@ mod tests { flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }) @@ -180,6 +182,7 @@ line-length = 79 flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }) @@ -212,6 +215,7 @@ exclude = ["foo.py"] flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }) @@ -244,6 +248,7 @@ select = ["E501"] flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }) @@ -277,6 +282,7 @@ ignore = ["E501"] flake8_annotations: None, flake8_bugbear: None, flake8_quotes: None, + flake8_tidy_imports: None, isort: None, pep8_naming: None, }) @@ -366,6 +372,9 @@ other-attribute = 1 docstring_quotes: Some(Quote::Double), avoid_escape: Some(true), }), + flake8_tidy_imports: Some(flake8_tidy_imports::settings::Options { + ban_relative_imports: Some(Strictness::Parents) + }), isort: None, pep8_naming: Some(pep8_naming::settings::Options { ignore_names: Some(vec![ diff --git a/src/settings/user.rs b/src/settings/user.rs index b2352cbfe9..690f3cdf49 100644 --- a/src/settings/user.rs +++ b/src/settings/user.rs @@ -7,7 +7,9 @@ use regex::Regex; use crate::checks::CheckCode; use crate::checks_gen::CheckCodePrefix; use crate::settings::types::{FilePattern, PythonVersion}; -use crate::{flake8_annotations, flake8_quotes, isort, pep8_naming, Configuration}; +use crate::{ + flake8_annotations, flake8_quotes, flake8_tidy_imports, isort, pep8_naming, Configuration, +}; /// Struct to render user-facing exclusion patterns. #[derive(Debug)] @@ -50,6 +52,7 @@ pub struct UserConfiguration { // Plugins pub flake8_annotations: flake8_annotations::settings::Settings, pub flake8_quotes: flake8_quotes::settings::Settings, + pub flake8_tidy_imports: flake8_tidy_imports::settings::Settings, pub isort: isort::settings::Settings, pub pep8_naming: pep8_naming::settings::Settings, // Non-settings exposed to the user @@ -95,6 +98,7 @@ impl UserConfiguration { target_version: configuration.target_version, flake8_annotations: configuration.flake8_annotations, flake8_quotes: configuration.flake8_quotes, + flake8_tidy_imports: configuration.flake8_tidy_imports, isort: configuration.isort, pep8_naming: configuration.pep8_naming, project_root,