From edd68a73c9abdf1f76b36d26c4fa79079397a67e Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Wed, 25 Jan 2023 03:53:40 +0100 Subject: [PATCH 1/3] refactor: Rename CLI arg structs from Cli to Args Technically the command-line interface (CLI) encompasses both input and output, so naming the input structs 'Args' is more accurate than 'Cli'. --- flake8_to_ruff/src/main.rs | 10 +++--- ruff_cli/src/{cli.rs => args.rs} | 12 ++++---- ruff_cli/src/commands.rs | 2 +- ruff_cli/src/lib.rs | 4 +-- ruff_cli/src/main.rs | 8 ++--- ruff_dev/src/generate_all.rs | 23 +++++++------- ruff_dev/src/generate_cli_help.rs | 9 +++--- ruff_dev/src/generate_json_schema.rs | 9 +++--- ruff_dev/src/generate_options.rs | 9 +++--- ruff_dev/src/generate_rules_table.rs | 9 +++--- ruff_dev/src/main.rs | 46 ++++++++++++++-------------- ruff_dev/src/print_ast.rs | 11 +++---- ruff_dev/src/print_cst.rs | 9 +++--- ruff_dev/src/print_tokens.rs | 9 +++--- ruff_dev/src/round_trip.rs | 11 +++---- 15 files changed, 86 insertions(+), 95 deletions(-) rename ruff_cli/src/{cli.rs => args.rs} (99%) diff --git a/flake8_to_ruff/src/main.rs b/flake8_to_ruff/src/main.rs index 3aff2f3398778..b226bcb1b45f6 100644 --- a/flake8_to_ruff/src/main.rs +++ b/flake8_to_ruff/src/main.rs @@ -26,7 +26,7 @@ use ruff::flake8_to_ruff::{self, ExternalConfig}; about = "Convert existing Flake8 configuration to Ruff.", long_about = None )] -struct Cli { +struct Args { /// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or /// `.flake8`). #[arg(required = true)] @@ -41,15 +41,15 @@ struct Cli { } fn main() -> Result<()> { - let cli = Cli::parse(); + let args = Args::parse(); // Read the INI file. let mut ini = Ini::new_cs(); ini.set_multiline(true); - let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?; + let config = ini.load(args.file).map_err(|msg| anyhow::anyhow!(msg))?; // Read the pyproject.toml file. - let pyproject = cli.pyproject.map(flake8_to_ruff::parse).transpose()?; + let pyproject = args.pyproject.map(flake8_to_ruff::parse).transpose()?; let external_config = pyproject .as_ref() .and_then(|pyproject| pyproject.tool.as_ref()) @@ -60,7 +60,7 @@ fn main() -> Result<()> { .unwrap_or_default(); // Create Ruff's pyproject.toml section. - let pyproject = flake8_to_ruff::convert(&config, &external_config, cli.plugin)?; + let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?; println!("{}", toml::to_string_pretty(&pyproject)?); Ok(()) diff --git a/ruff_cli/src/cli.rs b/ruff_cli/src/args.rs similarity index 99% rename from ruff_cli/src/cli.rs rename to ruff_cli/src/args.rs index 4c1c8bc00a822..6a2052283bf30 100644 --- a/ruff_cli/src/cli.rs +++ b/ruff_cli/src/args.rs @@ -19,7 +19,7 @@ use rustc_hash::FxHashMap; )] #[command(version)] #[allow(clippy::struct_excessive_bools)] -pub struct Cli { +pub struct Args { #[arg(required_unless_present_any = ["clean", "explain", "generate_shell_completion"])] pub files: Vec, /// Path to the `pyproject.toml` or `ruff.toml` file to use for @@ -231,7 +231,7 @@ pub struct Cli { pub show_settings: bool, } -impl Cli { +impl Args { /// Partition the CLI into command-line arguments and configuration /// overrides. pub fn partition(self) -> (Arguments, Overrides) { @@ -421,12 +421,12 @@ impl ConfigProcessor for &Overrides { } /// Map the CLI settings to a `LogLevel`. -pub fn extract_log_level(cli: &Arguments) -> LogLevel { - if cli.silent { +pub fn extract_log_level(args: &Arguments) -> LogLevel { + if args.silent { LogLevel::Silent - } else if cli.quiet { + } else if args.quiet { LogLevel::Quiet - } else if cli.verbose { + } else if args.verbose { LogLevel::Verbose } else { LogLevel::Default diff --git a/ruff_cli/src/commands.rs b/ruff_cli/src/commands.rs index 57eb4479986a9..badc4523ec3ed 100644 --- a/ruff_cli/src/commands.rs +++ b/ruff_cli/src/commands.rs @@ -23,8 +23,8 @@ use ruff::{fix, fs, packaging, resolver, warn_user_once, AutofixAvailability, IO use serde::Serialize; use walkdir::WalkDir; +use crate::args::Overrides; use crate::cache; -use crate::cli::Overrides; use crate::diagnostics::{lint_path, lint_stdin, Diagnostics}; use crate::iterators::par_iter; diff --git a/ruff_cli/src/lib.rs b/ruff_cli/src/lib.rs index cb0214e325ea9..bded7a5bf12e5 100644 --- a/ruff_cli/src/lib.rs +++ b/ruff_cli/src/lib.rs @@ -6,11 +6,11 @@ #![warn(clippy::pedantic)] #![allow(clippy::must_use_candidate, dead_code)] -mod cli; +mod args; use clap::CommandFactory; /// Returns the output of `ruff --help`. pub fn help() -> String { - cli::Cli::command().render_help().to_string() + args::Args::command().render_help().to_string() } diff --git a/ruff_cli/src/main.rs b/ruff_cli/src/main.rs index 3f1dd945f3ee6..90b3c74b6d09d 100644 --- a/ruff_cli/src/main.rs +++ b/ruff_cli/src/main.rs @@ -21,16 +21,16 @@ use ::ruff::settings::pyproject; use ::ruff::settings::types::SerializationFormat; use ::ruff::{fix, fs, warn_user_once}; use anyhow::Result; +use args::{extract_log_level, Args, Overrides}; use clap::{CommandFactory, Parser}; -use cli::{extract_log_level, Cli, Overrides}; use colored::Colorize; use notify::{recommended_watcher, RecursiveMode, Watcher}; use path_absolutize::path_dedot; use printer::{Printer, Violations}; use ruff::settings::{AllSettings, CliSettings}; +mod args; mod cache; -mod cli; mod commands; mod diagnostics; mod iterators; @@ -91,7 +91,7 @@ fn resolve( fn inner_main() -> Result { // Extract command-line arguments. - let (cli, overrides) = Cli::parse().partition(); + let (cli, overrides) = Args::parse().partition(); let default_panic_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { @@ -112,7 +112,7 @@ quoting the executed command, along with the relevant file contents and `pyproje set_up_logging(&log_level)?; if let Some(shell) = cli.generate_shell_completion { - shell.generate(&mut Cli::command(), &mut io::stdout()); + shell.generate(&mut Args::command(), &mut io::stdout()); return Ok(ExitCode::SUCCESS); } if cli.clean { diff --git a/ruff_dev/src/generate_all.rs b/ruff_dev/src/generate_all.rs index 5ebd728e67351..bba15fb2c24be 100644 --- a/ruff_dev/src/generate_all.rs +++ b/ruff_dev/src/generate_all.rs @@ -1,29 +1,28 @@ //! Run all code and documentation generation steps. use anyhow::Result; -use clap::Args; use crate::{generate_cli_help, generate_json_schema, generate_options, generate_rules_table}; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Write the generated artifacts to stdout (rather than to the filesystem). #[arg(long)] dry_run: bool, } -pub fn main(cli: &Cli) -> Result<()> { - generate_json_schema::main(&generate_json_schema::Cli { - dry_run: cli.dry_run, +pub fn main(args: &Args) -> Result<()> { + generate_json_schema::main(&generate_json_schema::Args { + dry_run: args.dry_run, })?; - generate_rules_table::main(&generate_rules_table::Cli { - dry_run: cli.dry_run, + generate_rules_table::main(&generate_rules_table::Args { + dry_run: args.dry_run, })?; - generate_options::main(&generate_options::Cli { - dry_run: cli.dry_run, + generate_options::main(&generate_options::Args { + dry_run: args.dry_run, })?; - generate_cli_help::main(&generate_cli_help::Cli { - dry_run: cli.dry_run, + generate_cli_help::main(&generate_cli_help::Args { + dry_run: args.dry_run, })?; Ok(()) } diff --git a/ruff_dev/src/generate_cli_help.rs b/ruff_dev/src/generate_cli_help.rs index 920f7451e7832..a88ba32827db5 100644 --- a/ruff_dev/src/generate_cli_help.rs +++ b/ruff_dev/src/generate_cli_help.rs @@ -1,15 +1,14 @@ //! Generate CLI help. use anyhow::Result; -use clap::Args; use crate::utils::replace_readme_section; const HELP_BEGIN_PRAGMA: &str = ""; const HELP_END_PRAGMA: &str = ""; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Write the generated help to stdout (rather than to `README.md`). #[arg(long)] pub(crate) dry_run: bool, @@ -19,10 +18,10 @@ fn trim_lines(s: &str) -> String { s.lines().map(str::trim_end).collect::>().join("\n") } -pub fn main(cli: &Cli) -> Result<()> { +pub fn main(args: &Args) -> Result<()> { let output = trim_lines(ruff_cli::help().trim()); - if cli.dry_run { + if args.dry_run { print!("{output}"); } else { replace_readme_section( diff --git a/ruff_dev/src/generate_json_schema.rs b/ruff_dev/src/generate_json_schema.rs index 1edf53ae1e197..a39dea475b4fa 100644 --- a/ruff_dev/src/generate_json_schema.rs +++ b/ruff_dev/src/generate_json_schema.rs @@ -2,22 +2,21 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; -use clap::Args; use ruff::settings::options::Options; use schemars::schema_for; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Write the generated table to stdout (rather than to `ruff.schema.json`). #[arg(long)] pub(crate) dry_run: bool, } -pub fn main(cli: &Cli) -> Result<()> { +pub fn main(args: &Args) -> Result<()> { let schema = schema_for!(Options); let schema_string = serde_json::to_string_pretty(&schema).unwrap(); - if cli.dry_run { + if args.dry_run { println!("{schema_string}"); } else { let file = PathBuf::from(env!("CARGO_MANIFEST_DIR")) diff --git a/ruff_dev/src/generate_options.rs b/ruff_dev/src/generate_options.rs index 689a72f2c82fc..32d4855f03a1e 100644 --- a/ruff_dev/src/generate_options.rs +++ b/ruff_dev/src/generate_options.rs @@ -1,7 +1,6 @@ //! Generate a Markdown-compatible listing of configuration options. use anyhow::Result; -use clap::Args; use itertools::Itertools; use ruff::settings::options::Options; use ruff::settings::options_base::{ConfigurationOptions, OptionEntry, OptionField}; @@ -11,8 +10,8 @@ use crate::utils::replace_readme_section; const BEGIN_PRAGMA: &str = ""; const END_PRAGMA: &str = ""; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Write the generated table to stdout (rather than to `README.md`). #[arg(long)] pub(crate) dry_run: bool, @@ -39,7 +38,7 @@ fn emit_field(output: &mut String, field: &OptionField, group_name: Option<&str> output.push('\n'); } -pub fn main(cli: &Cli) -> Result<()> { +pub fn main(args: &Args) -> Result<()> { let mut output = String::new(); // Generate all the top-level fields. @@ -89,7 +88,7 @@ pub fn main(cli: &Cli) -> Result<()> { } } - if cli.dry_run { + if args.dry_run { print!("{output}"); } else { replace_readme_section(&output, BEGIN_PRAGMA, END_PRAGMA)?; diff --git a/ruff_dev/src/generate_rules_table.rs b/ruff_dev/src/generate_rules_table.rs index 98dca6bb1be71..a320017cfae7d 100644 --- a/ruff_dev/src/generate_rules_table.rs +++ b/ruff_dev/src/generate_rules_table.rs @@ -1,7 +1,6 @@ //! Generate a Markdown-compatible table of supported lint rules. use anyhow::Result; -use clap::Args; use ruff::registry::{Linter, LinterCategory, Rule, RuleNamespace}; use strum::IntoEnumIterator; @@ -13,8 +12,8 @@ const TABLE_END_PRAGMA: &str = ""; const TOC_BEGIN_PRAGMA: &str = ""; const TOC_END_PRAGMA: &str = ""; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Write the generated table to stdout (rather than to `README.md`). #[arg(long)] pub(crate) dry_run: bool, @@ -43,7 +42,7 @@ fn generate_table(table_out: &mut String, rules: impl IntoIterator) table_out.push('\n'); } -pub fn main(cli: &Cli) -> Result<()> { +pub fn main(args: &Args) -> Result<()> { // Generate the table string. let mut table_out = String::new(); let mut toc_out = String::new(); @@ -96,7 +95,7 @@ pub fn main(cli: &Cli) -> Result<()> { } } - if cli.dry_run { + if args.dry_run { print!("Table of Contents: {toc_out}\n Rules Tables: {table_out}"); } else { // Extra newline in the markdown numbered list looks weird diff --git a/ruff_dev/src/main.rs b/ruff_dev/src/main.rs index 1c77096f46f40..2d543ad206f44 100644 --- a/ruff_dev/src/main.rs +++ b/ruff_dev/src/main.rs @@ -33,45 +33,45 @@ use clap::{Parser, Subcommand}; #[derive(Parser)] #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] -struct Cli { +struct Args { #[command(subcommand)] - command: Commands, + command: Command, } #[derive(Subcommand)] -enum Commands { +enum Command { /// Run all code and documentation generation steps. - GenerateAll(generate_all::Cli), + GenerateAll(generate_all::Args), /// Generate JSON schema for the TOML configuration file. - GenerateJSONSchema(generate_json_schema::Cli), + GenerateJSONSchema(generate_json_schema::Args), /// Generate a Markdown-compatible table of supported lint rules. - GenerateRulesTable(generate_rules_table::Cli), + GenerateRulesTable(generate_rules_table::Args), /// Generate a Markdown-compatible listing of configuration options. - GenerateOptions(generate_options::Cli), + GenerateOptions(generate_options::Args), /// Generate CLI help. - GenerateCliHelp(generate_cli_help::Cli), + GenerateCliHelp(generate_cli_help::Args), /// Print the AST for a given Python file. - PrintAST(print_ast::Cli), + PrintAST(print_ast::Args), /// Print the LibCST CST for a given Python file. - PrintCST(print_cst::Cli), + PrintCST(print_cst::Args), /// Print the token stream for a given Python file. - PrintTokens(print_tokens::Cli), + PrintTokens(print_tokens::Args), /// Run round-trip source code generation on a given Python file. - RoundTrip(round_trip::Cli), + RoundTrip(round_trip::Args), } fn main() -> Result<()> { - let cli = Cli::parse(); - match &cli.command { - Commands::GenerateAll(args) => generate_all::main(args)?, - Commands::GenerateJSONSchema(args) => generate_json_schema::main(args)?, - Commands::GenerateRulesTable(args) => generate_rules_table::main(args)?, - Commands::GenerateOptions(args) => generate_options::main(args)?, - Commands::GenerateCliHelp(args) => generate_cli_help::main(args)?, - Commands::PrintAST(args) => print_ast::main(args)?, - Commands::PrintCST(args) => print_cst::main(args)?, - Commands::PrintTokens(args) => print_tokens::main(args)?, - Commands::RoundTrip(args) => round_trip::main(args)?, + let args = Args::parse(); + match &args.command { + Command::GenerateAll(args) => generate_all::main(args)?, + Command::GenerateJSONSchema(args) => generate_json_schema::main(args)?, + Command::GenerateRulesTable(args) => generate_rules_table::main(args)?, + Command::GenerateOptions(args) => generate_options::main(args)?, + Command::GenerateCliHelp(args) => generate_cli_help::main(args)?, + Command::PrintAST(args) => print_ast::main(args)?, + Command::PrintCST(args) => print_cst::main(args)?, + Command::PrintTokens(args) => print_tokens::main(args)?, + Command::RoundTrip(args) => round_trip::main(args)?, } Ok(()) } diff --git a/ruff_dev/src/print_ast.rs b/ruff_dev/src/print_ast.rs index 1fccc2941537b..7d0e0d4769e65 100644 --- a/ruff_dev/src/print_ast.rs +++ b/ruff_dev/src/print_ast.rs @@ -4,19 +4,18 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; -use clap::Args; use rustpython_parser::parser; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Python file for which to generate the AST. #[arg(required = true)] file: PathBuf, } -pub fn main(cli: &Cli) -> Result<()> { - let contents = fs::read_to_string(&cli.file)?; - let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?; +pub fn main(args: &Args) -> Result<()> { + let contents = fs::read_to_string(&args.file)?; + let python_ast = parser::parse_program(&contents, &args.file.to_string_lossy())?; println!("{python_ast:#?}"); Ok(()) } diff --git a/ruff_dev/src/print_cst.rs b/ruff_dev/src/print_cst.rs index abd6953515b54..943d9dc6df19f 100644 --- a/ruff_dev/src/print_cst.rs +++ b/ruff_dev/src/print_cst.rs @@ -4,17 +4,16 @@ use std::fs; use std::path::PathBuf; use anyhow::{bail, Result}; -use clap::Args; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Python file for which to generate the CST. #[arg(required = true)] file: PathBuf, } -pub fn main(cli: &Cli) -> Result<()> { - let contents = fs::read_to_string(&cli.file)?; +pub fn main(args: &Args) -> Result<()> { + let contents = fs::read_to_string(&args.file)?; match libcst_native::parse_module(&contents, None) { Ok(python_cst) => { println!("{python_cst:#?}"); diff --git a/ruff_dev/src/print_tokens.rs b/ruff_dev/src/print_tokens.rs index be867c80d2d7e..1b3d2f2135489 100644 --- a/ruff_dev/src/print_tokens.rs +++ b/ruff_dev/src/print_tokens.rs @@ -4,18 +4,17 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; -use clap::Args; use rustpython_parser::lexer; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Python file for which to generate the AST. #[arg(required = true)] file: PathBuf, } -pub fn main(cli: &Cli) -> Result<()> { - let contents = fs::read_to_string(&cli.file)?; +pub fn main(args: &Args) -> Result<()> { + let contents = fs::read_to_string(&args.file)?; for (_, tok, _) in lexer::make_tokenizer(&contents).flatten() { println!("{tok:#?}"); } diff --git a/ruff_dev/src/round_trip.rs b/ruff_dev/src/round_trip.rs index 1df3fdfb3ef52..f196a368d0965 100644 --- a/ruff_dev/src/round_trip.rs +++ b/ruff_dev/src/round_trip.rs @@ -4,18 +4,17 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; -use clap::Args; use ruff::source_code::round_trip; -#[derive(Args)] -pub struct Cli { +#[derive(clap::Args)] +pub struct Args { /// Python file to round-trip. #[arg(required = true)] file: PathBuf, } -pub fn main(cli: &Cli) -> Result<()> { - let contents = fs::read_to_string(&cli.file)?; - println!("{}", round_trip(&contents, &cli.file.to_string_lossy())?); +pub fn main(args: &Args) -> Result<()> { + let contents = fs::read_to_string(&args.file)?; + println!("{}", round_trip(&contents, &args.file.to_string_lossy())?); Ok(()) } From 43be6c5178916c905077e8eaf837d63a4ada9c7d Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Wed, 25 Jan 2023 07:58:48 +0100 Subject: [PATCH 2/3] refactor: Move ruff_cli::resolve to own module --- ruff_cli/src/main.rs | 69 +++++------------------------------------ ruff_cli/src/resolve.rs | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 62 deletions(-) create mode 100644 ruff_cli/src/resolve.rs diff --git a/ruff_cli/src/main.rs b/ruff_cli/src/main.rs index 90b3c74b6d09d..587449b6c5b0b 100644 --- a/ruff_cli/src/main.rs +++ b/ruff_cli/src/main.rs @@ -8,87 +8,32 @@ )] use std::io::{self}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::ExitCode; use std::sync::mpsc::channel; use ::ruff::logging::{set_up_logging, LogLevel}; -use ::ruff::resolver::{ - resolve_settings_with_processor, ConfigProcessor, FileDiscovery, PyprojectDiscovery, Relativity, -}; -use ::ruff::settings::configuration::Configuration; -use ::ruff::settings::pyproject; +use ::ruff::resolver::{FileDiscovery, PyprojectDiscovery}; use ::ruff::settings::types::SerializationFormat; use ::ruff::{fix, fs, warn_user_once}; use anyhow::Result; -use args::{extract_log_level, Args, Overrides}; +use args::{extract_log_level, Args}; use clap::{CommandFactory, Parser}; use colored::Colorize; use notify::{recommended_watcher, RecursiveMode, Watcher}; -use path_absolutize::path_dedot; use printer::{Printer, Violations}; -use ruff::settings::{AllSettings, CliSettings}; +use ruff::settings::CliSettings; -mod args; +pub(crate) mod args; mod cache; mod commands; mod diagnostics; mod iterators; mod printer; +mod resolve; #[cfg(all(feature = "update-informer"))] pub mod updates; -/// Resolve the relevant settings strategy and defaults for the current -/// invocation. -fn resolve( - isolated: bool, - config: Option<&Path>, - overrides: &Overrides, - stdin_filename: Option<&Path>, -) -> Result { - if isolated { - // First priority: if we're running in isolated mode, use the default settings. - let mut config = Configuration::default(); - overrides.process_config(&mut config); - let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; - Ok(PyprojectDiscovery::Fixed(settings)) - } else if let Some(pyproject) = config { - // Second priority: the user specified a `pyproject.toml` file. Use that - // `pyproject.toml` for _all_ configuration, and resolve paths relative to the - // current working directory. (This matches ESLint's behavior.) - let settings = resolve_settings_with_processor(pyproject, &Relativity::Cwd, overrides)?; - Ok(PyprojectDiscovery::Fixed(settings)) - } else if let Some(pyproject) = pyproject::find_settings_toml( - stdin_filename - .as_ref() - .unwrap_or(&path_dedot::CWD.as_path()), - )? { - // Third priority: find a `pyproject.toml` file in either an ancestor of - // `stdin_filename` (if set) or the current working path all paths relative to - // that directory. (With `Strategy::Hierarchical`, we'll end up finding - // the "closest" `pyproject.toml` file for every Python file later on, - // so these act as the "default" settings.) - let settings = resolve_settings_with_processor(&pyproject, &Relativity::Parent, overrides)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) - } else if let Some(pyproject) = pyproject::find_user_settings_toml() { - // Fourth priority: find a user-specific `pyproject.toml`, but resolve all paths - // relative the current working directory. (With `Strategy::Hierarchical`, we'll - // end up the "closest" `pyproject.toml` file for every Python file later on, so - // these act as the "default" settings.) - let settings = resolve_settings_with_processor(&pyproject, &Relativity::Cwd, overrides)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) - } else { - // Fallback: load Ruff's default settings, and resolve all paths relative to the - // current working directory. (With `Strategy::Hierarchical`, we'll end up the - // "closest" `pyproject.toml` file for every Python file later on, so these act - // as the "default" settings.) - let mut config = Configuration::default(); - overrides.process_config(&mut config); - let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) - } -} - fn inner_main() -> Result { // Extract command-line arguments. let (cli, overrides) = Args::parse().partition(); @@ -122,7 +67,7 @@ quoting the executed command, along with the relevant file contents and `pyproje // Construct the "default" settings. These are used when no `pyproject.toml` // files are present, or files are injected from outside of the hierarchy. - let pyproject_strategy = resolve( + let pyproject_strategy = resolve::resolve( cli.isolated, cli.config.as_deref(), &overrides, diff --git a/ruff_cli/src/resolve.rs b/ruff_cli/src/resolve.rs new file mode 100644 index 0000000000000..60bd0c8771b59 --- /dev/null +++ b/ruff_cli/src/resolve.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use anyhow::Result; +use path_absolutize::path_dedot; +use ruff::resolver::{ + resolve_settings_with_processor, ConfigProcessor, PyprojectDiscovery, Relativity, +}; +use ruff::settings::configuration::Configuration; +use ruff::settings::{pyproject, AllSettings}; + +use crate::args::Overrides; + +/// Resolve the relevant settings strategy and defaults for the current +/// invocation. +pub fn resolve( + isolated: bool, + config: Option<&Path>, + overrides: &Overrides, + stdin_filename: Option<&Path>, +) -> Result { + if isolated { + // First priority: if we're running in isolated mode, use the default settings. + let mut config = Configuration::default(); + overrides.process_config(&mut config); + let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; + Ok(PyprojectDiscovery::Fixed(settings)) + } else if let Some(pyproject) = config { + // Second priority: the user specified a `pyproject.toml` file. Use that + // `pyproject.toml` for _all_ configuration, and resolve paths relative to the + // current working directory. (This matches ESLint's behavior.) + let settings = resolve_settings_with_processor(pyproject, &Relativity::Cwd, overrides)?; + Ok(PyprojectDiscovery::Fixed(settings)) + } else if let Some(pyproject) = pyproject::find_settings_toml( + stdin_filename + .as_ref() + .unwrap_or(&path_dedot::CWD.as_path()), + )? { + // Third priority: find a `pyproject.toml` file in either an ancestor of + // `stdin_filename` (if set) or the current working path all paths relative to + // that directory. (With `Strategy::Hierarchical`, we'll end up finding + // the "closest" `pyproject.toml` file for every Python file later on, + // so these act as the "default" settings.) + let settings = resolve_settings_with_processor(&pyproject, &Relativity::Parent, overrides)?; + Ok(PyprojectDiscovery::Hierarchical(settings)) + } else if let Some(pyproject) = pyproject::find_user_settings_toml() { + // Fourth priority: find a user-specific `pyproject.toml`, but resolve all paths + // relative the current working directory. (With `Strategy::Hierarchical`, we'll + // end up the "closest" `pyproject.toml` file for every Python file later on, so + // these act as the "default" settings.) + let settings = resolve_settings_with_processor(&pyproject, &Relativity::Cwd, overrides)?; + Ok(PyprojectDiscovery::Hierarchical(settings)) + } else { + // Fallback: load Ruff's default settings, and resolve all paths relative to the + // current working directory. (With `Strategy::Hierarchical`, we'll end up the + // "closest" `pyproject.toml` file for every Python file later on, so these act + // as the "default" settings.) + let mut config = Configuration::default(); + overrides.process_config(&mut config); + let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; + Ok(PyprojectDiscovery::Hierarchical(settings)) + } +} From 886b887fc58c967a35b8597797708177008826d4 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Wed, 25 Jan 2023 05:25:30 +0100 Subject: [PATCH 3/3] refactor: Move comments before if conditions --- ruff_cli/src/resolve.rs | 64 ++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/ruff_cli/src/resolve.rs b/ruff_cli/src/resolve.rs index 60bd0c8771b59..c52166c6a55d6 100644 --- a/ruff_cli/src/resolve.rs +++ b/ruff_cli/src/resolve.rs @@ -18,45 +18,51 @@ pub fn resolve( overrides: &Overrides, stdin_filename: Option<&Path>, ) -> Result { + // First priority: if we're running in isolated mode, use the default settings. if isolated { - // First priority: if we're running in isolated mode, use the default settings. let mut config = Configuration::default(); overrides.process_config(&mut config); let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; - Ok(PyprojectDiscovery::Fixed(settings)) - } else if let Some(pyproject) = config { - // Second priority: the user specified a `pyproject.toml` file. Use that - // `pyproject.toml` for _all_ configuration, and resolve paths relative to the - // current working directory. (This matches ESLint's behavior.) + return Ok(PyprojectDiscovery::Fixed(settings)); + } + + // Second priority: the user specified a `pyproject.toml` file. Use that + // `pyproject.toml` for _all_ configuration, and resolve paths relative to the + // current working directory. (This matches ESLint's behavior.) + if let Some(pyproject) = config { let settings = resolve_settings_with_processor(pyproject, &Relativity::Cwd, overrides)?; - Ok(PyprojectDiscovery::Fixed(settings)) - } else if let Some(pyproject) = pyproject::find_settings_toml( + return Ok(PyprojectDiscovery::Fixed(settings)); + } + + // Third priority: find a `pyproject.toml` file in either an ancestor of + // `stdin_filename` (if set) or the current working path all paths relative to + // that directory. (With `Strategy::Hierarchical`, we'll end up finding + // the "closest" `pyproject.toml` file for every Python file later on, + // so these act as the "default" settings.) + if let Some(pyproject) = pyproject::find_settings_toml( stdin_filename .as_ref() .unwrap_or(&path_dedot::CWD.as_path()), )? { - // Third priority: find a `pyproject.toml` file in either an ancestor of - // `stdin_filename` (if set) or the current working path all paths relative to - // that directory. (With `Strategy::Hierarchical`, we'll end up finding - // the "closest" `pyproject.toml` file for every Python file later on, - // so these act as the "default" settings.) let settings = resolve_settings_with_processor(&pyproject, &Relativity::Parent, overrides)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) - } else if let Some(pyproject) = pyproject::find_user_settings_toml() { - // Fourth priority: find a user-specific `pyproject.toml`, but resolve all paths - // relative the current working directory. (With `Strategy::Hierarchical`, we'll - // end up the "closest" `pyproject.toml` file for every Python file later on, so - // these act as the "default" settings.) + return Ok(PyprojectDiscovery::Hierarchical(settings)); + } + + // Fourth priority: find a user-specific `pyproject.toml`, but resolve all paths + // relative the current working directory. (With `Strategy::Hierarchical`, we'll + // end up the "closest" `pyproject.toml` file for every Python file later on, so + // these act as the "default" settings.) + if let Some(pyproject) = pyproject::find_user_settings_toml() { let settings = resolve_settings_with_processor(&pyproject, &Relativity::Cwd, overrides)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) - } else { - // Fallback: load Ruff's default settings, and resolve all paths relative to the - // current working directory. (With `Strategy::Hierarchical`, we'll end up the - // "closest" `pyproject.toml` file for every Python file later on, so these act - // as the "default" settings.) - let mut config = Configuration::default(); - overrides.process_config(&mut config); - let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; - Ok(PyprojectDiscovery::Hierarchical(settings)) + return Ok(PyprojectDiscovery::Hierarchical(settings)); } + + // Fallback: load Ruff's default settings, and resolve all paths relative to the + // current working directory. (With `Strategy::Hierarchical`, we'll end up the + // "closest" `pyproject.toml` file for every Python file later on, so these act + // as the "default" settings.) + let mut config = Configuration::default(); + overrides.process_config(&mut config); + let settings = AllSettings::from_configuration(config, &path_dedot::CWD)?; + Ok(PyprojectDiscovery::Hierarchical(settings)) }