diff --git a/flake8_to_ruff/src/main.rs b/flake8_to_ruff/src/main.rs index 97f772eed8eb0..279df5bb5cf75 100644 --- a/flake8_to_ruff/src/main.rs +++ b/flake8_to_ruff/src/main.rs @@ -18,7 +18,7 @@ use std::path::PathBuf; use anyhow::Result; use clap::Parser; use configparser::ini::Ini; -use ruff::flake8_to_ruff; +use ruff::flake8_to_ruff::{self, ExternalConfig}; #[derive(Parser)] #[command( @@ -48,14 +48,18 @@ fn main() -> Result<()> { let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?; // Read the pyproject.toml file. - let black = cli - .pyproject - .map(flake8_to_ruff::parse_black_options) - .transpose()? - .flatten(); + let pyproject = cli.pyproject.map(flake8_to_ruff::parse).transpose()?; + let external_config = pyproject + .as_ref() + .and_then(|pyproject| pyproject.tool.as_ref()) + .map(|tool| ExternalConfig { + black: tool.black.as_ref(), + isort: tool.isort.as_ref(), + }) + .unwrap_or_default(); // Create Ruff's pyproject.toml section. - let pyproject = flake8_to_ruff::convert(&config, black.as_ref(), cli.plugin)?; + let pyproject = flake8_to_ruff::convert(&config, &external_config, cli.plugin)?; println!("{}", toml_edit::easy::to_string_pretty(&pyproject)?); Ok(()) diff --git a/src/flake8_to_ruff/black.rs b/src/flake8_to_ruff/black.rs index 0807607be00cd..b1e2e5e601cf7 100644 --- a/src/flake8_to_ruff/black.rs +++ b/src/flake8_to_ruff/black.rs @@ -1,8 +1,5 @@ //! Extract Black configuration settings from a pyproject.toml. -use std::path::Path; - -use anyhow::Result; use serde::{Deserialize, Serialize}; use crate::settings::types::PythonVersion; @@ -14,20 +11,3 @@ pub struct Black { #[serde(alias = "target-version", alias = "target_version")] pub target_version: Option>, } - -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -struct Tools { - black: Option, -} - -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -struct Pyproject { - tool: Option, -} - -pub fn parse_black_options>(path: P) -> Result> { - let contents = std::fs::read_to_string(path)?; - Ok(toml_edit::easy::from_str::(&contents)? - .tool - .and_then(|tool| tool.black)) -} diff --git a/src/flake8_to_ruff/converter.rs b/src/flake8_to_ruff/converter.rs index c8f9f8ddb6af6..58855a2a5ccef 100644 --- a/src/flake8_to_ruff/converter.rs +++ b/src/flake8_to_ruff/converter.rs @@ -3,7 +3,7 @@ use std::collections::{BTreeSet, HashMap}; use anyhow::Result; use colored::Colorize; -use super::black::Black; +use super::external_config::ExternalConfig; use super::plugin::Plugin; use super::{parser, plugin}; use crate::registry::RuleSelector; @@ -23,7 +23,7 @@ use crate::warn_user; pub fn convert( config: &HashMap>>, - black: Option<&Black>, + external_config: &ExternalConfig, plugins: Option>, ) -> Result { // Extract the Flake8 section. @@ -377,7 +377,7 @@ pub fn convert( } // Extract any settings from the existing `pyproject.toml`. - if let Some(black) = black { + if let Some(black) = &external_config.black { if let Some(line_length) = &black.line_length { options.line_length = Some(*line_length); } @@ -389,6 +389,19 @@ pub fn convert( } } + if let Some(isort) = &external_config.isort { + if let Some(src_paths) = &isort.src_paths { + match options.src.as_mut() { + Some(src) => { + src.extend(src_paths.clone()); + } + None => { + options.src = Some(src_paths.clone()); + } + } + } + } + // Create the pyproject.toml. Ok(Pyproject::new(options)) } @@ -401,6 +414,7 @@ mod tests { use super::super::plugin::Plugin; use super::convert; + use crate::flake8_to_ruff::ExternalConfig; use crate::registry::RuleSelector; use crate::rules::pydocstyle::settings::Convention; use crate::rules::{flake8_quotes, pydocstyle}; @@ -411,7 +425,7 @@ mod tests { fn it_converts_empty() -> Result<()> { let actual = convert( &HashMap::from([("flake8".to_string(), HashMap::default())]), - None, + &ExternalConfig::default(), None, )?; let expected = Pyproject::new(Options { @@ -475,7 +489,7 @@ mod tests { "flake8".to_string(), HashMap::from([("max-line-length".to_string(), Some("100".to_string()))]), )]), - None, + &ExternalConfig::default(), Some(vec![]), )?; let expected = Pyproject::new(Options { @@ -539,7 +553,7 @@ mod tests { "flake8".to_string(), HashMap::from([("max_line_length".to_string(), Some("100".to_string()))]), )]), - None, + &ExternalConfig::default(), Some(vec![]), )?; let expected = Pyproject::new(Options { @@ -603,7 +617,7 @@ mod tests { "flake8".to_string(), HashMap::from([("max_line_length".to_string(), Some("abc".to_string()))]), )]), - None, + &ExternalConfig::default(), Some(vec![]), )?; let expected = Pyproject::new(Options { @@ -667,7 +681,7 @@ mod tests { "flake8".to_string(), HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]), )]), - None, + &ExternalConfig::default(), Some(vec![]), )?; let expected = Pyproject::new(Options { @@ -739,7 +753,7 @@ mod tests { Some("numpy".to_string()), )]), )]), - None, + &ExternalConfig::default(), Some(vec![Plugin::Flake8Docstrings]), )?; let expected = Pyproject::new(Options { @@ -810,7 +824,7 @@ mod tests { "flake8".to_string(), HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]), )]), - None, + &ExternalConfig::default(), None, )?; let expected = Pyproject::new(Options { diff --git a/src/flake8_to_ruff/external_config.rs b/src/flake8_to_ruff/external_config.rs new file mode 100644 index 0000000000000..b93894cd7089c --- /dev/null +++ b/src/flake8_to_ruff/external_config.rs @@ -0,0 +1,8 @@ +use super::black::Black; +use super::isort::Isort; + +#[derive(Default)] +pub struct ExternalConfig<'a> { + pub black: Option<&'a Black>, + pub isort: Option<&'a Isort>, +} diff --git a/src/flake8_to_ruff/isort.rs b/src/flake8_to_ruff/isort.rs new file mode 100644 index 0000000000000..86af2037b2af1 --- /dev/null +++ b/src/flake8_to_ruff/isort.rs @@ -0,0 +1,10 @@ +//! Extract isort configuration settings from a pyproject.toml. + +use serde::{Deserialize, Serialize}; + +/// The [isort configuration](https://pycqa.github.io/isort/docs/configuration/config_files.html). +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct Isort { + #[serde(alias = "src-paths", alias = "src_paths")] + pub src_paths: Option>, +} diff --git a/src/flake8_to_ruff/mod.rs b/src/flake8_to_ruff/mod.rs index eec0d5986d6aa..3f7776c2561ea 100644 --- a/src/flake8_to_ruff/mod.rs +++ b/src/flake8_to_ruff/mod.rs @@ -1,8 +1,12 @@ mod black; mod converter; +mod external_config; +mod isort; mod parser; mod plugin; +mod pyproject; -pub use black::parse_black_options; pub use converter::convert; +pub use external_config::ExternalConfig; pub use plugin::Plugin; +pub use pyproject::parse; diff --git a/src/flake8_to_ruff/pyproject.rs b/src/flake8_to_ruff/pyproject.rs new file mode 100644 index 0000000000000..335c7d2fc1112 --- /dev/null +++ b/src/flake8_to_ruff/pyproject.rs @@ -0,0 +1,24 @@ +use std::path::Path; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; + +use super::black::Black; +use super::isort::Isort; + +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Tools { + pub black: Option, + pub isort: Option, +} + +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Pyproject { + pub tool: Option, +} + +pub fn parse>(path: P) -> Result { + let contents = std::fs::read_to_string(path)?; + let pyproject = toml_edit::easy::from_str::(&contents)?; + Ok(pyproject) +}