diff --git a/crates/ruff/src/args.rs b/crates/ruff/src/args.rs index 329c5557dac50..022d5c6f2452f 100644 --- a/crates/ruff/src/args.rs +++ b/crates/ruff/src/args.rs @@ -28,6 +28,52 @@ use ruff_workspace::configuration::{Configuration, RuleSelection}; use ruff_workspace::options::{Options, PycodestyleOptions}; use ruff_workspace::resolver::ConfigurationTransformer; +/// All configuration options that can be passed "globally", +/// i.e., can be passed to all subcommands +#[derive(Debug, Default, Clone, clap::Args)] +pub struct GlobalConfigArgs { + #[clap(flatten)] + log_level_args: LogLevelArgs, + /// Either a path to a TOML configuration file (`pyproject.toml` or `ruff.toml`), + /// or a TOML ` = ` pair + /// (such as you might find in a `ruff.toml` configuration file) + /// overriding a specific configuration option. + /// Overrides of individual settings using this option always take precedence + /// over all configuration files, including configuration files that were also + /// specified using `--config`. + #[arg( + long, + action = clap::ArgAction::Append, + value_name = "CONFIG_OPTION", + value_parser = ConfigArgumentParser, + global = true, + help_heading = "Global options", + )] + pub config: Vec, + /// Ignore all configuration files. + // + // Note: We can't mark this as conflicting with `--config` here + // as `--config` can be used for specifying configuration overrides + // as well as configuration files. + // Specifying a configuration file conflicts with `--isolated`; + // specifying a configuration override does not. + // If a user specifies `ruff check --isolated --config=ruff.toml`, + // we emit an error later on, after the initial parsing by clap. + #[arg(long, help_heading = "Global options", global = true)] + pub isolated: bool, +} + +impl GlobalConfigArgs { + pub fn log_level(&self) -> LogLevel { + LogLevel::from(&self.log_level_args) + } + + #[must_use] + fn partition(self) -> (LogLevel, Vec, bool) { + (self.log_level(), self.config, self.isolated) + } +} + #[derive(Debug, Parser)] #[command( author, @@ -38,9 +84,9 @@ use ruff_workspace::resolver::ConfigurationTransformer; #[command(version)] pub struct Args { #[command(subcommand)] - pub command: Command, + pub(crate) command: Command, #[clap(flatten)] - pub log_level_args: LogLevelArgs, + pub(crate) global_options: GlobalConfigArgs, } #[allow(clippy::large_enum_variant)] @@ -153,20 +199,6 @@ pub struct CheckCommand { preview: bool, #[clap(long, overrides_with("preview"), hide = true)] no_preview: bool, - /// Either a path to a TOML configuration file (`pyproject.toml` or `ruff.toml`), - /// or a TOML ` = ` pair - /// (such as you might find in a `ruff.toml` configuration file) - /// overriding a specific configuration option. - /// Overrides of individual settings using this option always take precedence - /// over all configuration files, including configuration files that were also - /// specified using `--config`. - #[arg( - long, - action = clap::ArgAction::Append, - value_name = "CONFIG_OPTION", - value_parser = ConfigArgumentParser, - )] - pub config: Vec, /// Comma-separated list of rule codes to enable (or ALL, to enable all rules). #[arg( long, @@ -298,17 +330,6 @@ pub struct CheckCommand { /// Disable cache reads. #[arg(short, long, env = "RUFF_NO_CACHE", help_heading = "Miscellaneous")] pub no_cache: bool, - /// Ignore all configuration files. - // - // Note: We can't mark this as conflicting with `--config` here - // as `--config` can be used for specifying configuration overrides - // as well as configuration files. - // Specifying a configuration file conflicts with `--isolated`; - // specifying a configuration override does not. - // If a user specifies `ruff check --isolated --config=ruff.toml`, - // we emit an error later on, after the initial parsing by clap. - #[arg(long, help_heading = "Miscellaneous")] - pub isolated: bool, /// Path to the cache directory. #[arg(long, env = "RUFF_CACHE_DIR", help_heading = "Miscellaneous")] pub cache_dir: Option, @@ -400,20 +421,6 @@ pub struct FormatCommand { /// difference between the current file and how the formatted file would look like. #[arg(long)] pub diff: bool, - /// Either a path to a TOML configuration file (`pyproject.toml` or `ruff.toml`), - /// or a TOML ` = ` pair - /// (such as you might find in a `ruff.toml` configuration file) - /// overriding a specific configuration option. - /// Overrides of individual settings using this option always take precedence - /// over all configuration files, including configuration files that were also - /// specified using `--config`. - #[arg( - long, - action = clap::ArgAction::Append, - value_name = "CONFIG_OPTION", - value_parser = ConfigArgumentParser, - )] - pub config: Vec, /// Disable cache reads. #[arg(short, long, env = "RUFF_NO_CACHE", help_heading = "Miscellaneous")] @@ -454,17 +461,6 @@ pub struct FormatCommand { /// Set the line-length. #[arg(long, help_heading = "Format configuration")] pub line_length: Option, - /// Ignore all configuration files. - // - // Note: We can't mark this as conflicting with `--config` here - // as `--config` can be used for specifying configuration overrides - // as well as configuration files. - // Specifying a configuration file conflicts with `--isolated`; - // specifying a configuration override does not. - // If a user specifies `ruff check --isolated --config=ruff.toml`, - // we emit an error later on, after the initial parsing by clap. - #[arg(long, help_heading = "Miscellaneous")] - pub isolated: bool, /// The name of the file when passing it through stdin. #[arg(long, help_heading = "Miscellaneous")] pub stdin_filename: Option, @@ -505,7 +501,7 @@ pub enum HelpFormat { } #[allow(clippy::module_name_repetitions)] -#[derive(Debug, clap::Args)] +#[derive(Debug, Default, Clone, clap::Args)] pub struct LogLevelArgs { /// Enable verbose logging. #[arg( @@ -553,6 +549,10 @@ impl From<&LogLevelArgs> for LogLevel { /// Configuration-related arguments passed via the CLI. #[derive(Default)] pub struct ConfigArguments { + /// Whether the user specified --isolated on the command line + pub(crate) isolated: bool, + /// The logging level to be used, derived from command-line arguments passed + pub(crate) log_level: LogLevel, /// Path to a pyproject.toml or ruff.toml configuration file (etc.). /// Either 0 or 1 configuration file paths may be provided on the command line. config_file: Option, @@ -573,21 +573,19 @@ impl ConfigArguments { } fn from_cli_arguments( - config_options: Vec, + global_options: GlobalConfigArgs, per_flag_overrides: ExplicitConfigOverrides, - isolated: bool, ) -> anyhow::Result { - let mut new = Self { - per_flag_overrides, - ..Self::default() - }; + let (log_level, config_options, isolated) = global_options.partition(); + let mut config_file: Option = None; + let mut overrides = Configuration::default(); for option in config_options { match option { SingleConfigArgument::SettingsOverride(overridden_option) => { let overridden_option = Arc::try_unwrap(overridden_option) .unwrap_or_else(|option| option.deref().clone()); - new.overrides = new.overrides.combine(Configuration::from_options( + overrides = overrides.combine(Configuration::from_options( overridden_option, None, &path_dedot::CWD, @@ -606,7 +604,7 @@ The argument `--config={}` cannot be used with `--isolated` path.display() ); } - if let Some(ref config_file) = new.config_file { + if let Some(ref config_file) = config_file { let (first, second) = (config_file.display(), path.display()); bail!( "\ @@ -617,11 +615,17 @@ You cannot specify more than one configuration file on the command line. " ); } - new.config_file = Some(path); + config_file = Some(path); } } } - Ok(new) + Ok(Self { + isolated, + log_level, + config_file, + overrides, + per_flag_overrides, + }) } } @@ -635,7 +639,10 @@ impl ConfigurationTransformer for ConfigArguments { impl CheckCommand { /// Partition the CLI into command-line arguments and configuration /// overrides. - pub fn partition(self) -> anyhow::Result<(CheckArguments, ConfigArguments)> { + pub fn partition( + self, + global_options: GlobalConfigArgs, + ) -> anyhow::Result<(CheckArguments, ConfigArguments)> { let check_arguments = CheckArguments { add_noqa: self.add_noqa, diff: self.diff, @@ -644,7 +651,6 @@ impl CheckCommand { exit_zero: self.exit_zero, files: self.files, ignore_noqa: self.ignore_noqa, - isolated: self.isolated, no_cache: self.no_cache, output_file: self.output_file, show_files: self.show_files, @@ -688,8 +694,7 @@ impl CheckCommand { extension: self.extension, }; - let config_args = - ConfigArguments::from_cli_arguments(self.config, cli_overrides, self.isolated)?; + let config_args = ConfigArguments::from_cli_arguments(global_options, cli_overrides)?; Ok((check_arguments, config_args)) } } @@ -697,12 +702,14 @@ impl CheckCommand { impl FormatCommand { /// Partition the CLI into command-line arguments and configuration /// overrides. - pub fn partition(self) -> anyhow::Result<(FormatArguments, ConfigArguments)> { + pub fn partition( + self, + global_options: GlobalConfigArgs, + ) -> anyhow::Result<(FormatArguments, ConfigArguments)> { let format_arguments = FormatArguments { check: self.check, diff: self.diff, files: self.files, - isolated: self.isolated, no_cache: self.no_cache, stdin_filename: self.stdin_filename, range: self.range, @@ -722,8 +729,7 @@ impl FormatCommand { ..ExplicitConfigOverrides::default() }; - let config_args = - ConfigArguments::from_cli_arguments(self.config, cli_overrides, self.isolated)?; + let config_args = ConfigArguments::from_cli_arguments(global_options, cli_overrides)?; Ok((format_arguments, config_args)) } } @@ -949,7 +955,6 @@ pub struct CheckArguments { pub exit_zero: bool, pub files: Vec, pub ignore_noqa: bool, - pub isolated: bool, pub no_cache: bool, pub output_file: Option, pub show_files: bool, @@ -967,7 +972,6 @@ pub struct FormatArguments { pub no_cache: bool, pub diff: bool, pub files: Vec, - pub isolated: bool, pub stdin_filename: Option, pub range: Option, } diff --git a/crates/ruff/src/commands/format.rs b/crates/ruff/src/commands/format.rs index 185d79ff1f909..0c3e94409f977 100644 --- a/crates/ruff/src/commands/format.rs +++ b/crates/ruff/src/commands/format.rs @@ -61,13 +61,8 @@ impl FormatMode { pub(crate) fn format( cli: FormatArguments, config_arguments: &ConfigArguments, - log_level: LogLevel, ) -> Result { - let pyproject_config = resolve( - cli.isolated, - config_arguments, - cli.stdin_filename.as_deref(), - )?; + let pyproject_config = resolve(config_arguments, cli.stdin_filename.as_deref())?; let mode = FormatMode::from_cli(&cli); let files = resolve_default_files(cli.files, false); let (paths, resolver) = python_files_in_path(&files, &pyproject_config, config_arguments)?; @@ -202,7 +197,7 @@ pub(crate) fn format( } // Report on the formatting changes. - if log_level >= LogLevel::Default { + if config_arguments.log_level >= LogLevel::Default { if mode.is_diff() { // Allow piping the diff to e.g. a file by writing the summary to stderr results.write_summary(&mut stderr().lock())?; diff --git a/crates/ruff/src/commands/format_stdin.rs b/crates/ruff/src/commands/format_stdin.rs index bb3f7eb7bebd6..9c2d8ff3e0e07 100644 --- a/crates/ruff/src/commands/format_stdin.rs +++ b/crates/ruff/src/commands/format_stdin.rs @@ -23,11 +23,7 @@ pub(crate) fn format_stdin( cli: &FormatArguments, config_arguments: &ConfigArguments, ) -> Result { - let pyproject_config = resolve( - cli.isolated, - config_arguments, - cli.stdin_filename.as_deref(), - )?; + let pyproject_config = resolve(config_arguments, cli.stdin_filename.as_deref())?; let mut resolver = Resolver::new(&pyproject_config); warn_incompatible_formatter_settings(&resolver); diff --git a/crates/ruff/src/lib.rs b/crates/ruff/src/lib.rs index 5a3e66e8932b4..cb5954a987e38 100644 --- a/crates/ruff/src/lib.rs +++ b/crates/ruff/src/lib.rs @@ -7,6 +7,7 @@ use std::process::ExitCode; use std::sync::mpsc::channel; use anyhow::Result; +use args::GlobalConfigArgs; use clap::CommandFactory; use colored::Colorize; use log::warn; @@ -117,7 +118,7 @@ fn resolve_default_files(files: Vec, is_stdin: bool) -> Vec { pub fn run( Args { command, - log_level_args, + global_options, }: Args, deprecated_alias_warning: Option<&'static str>, ) -> Result { @@ -147,8 +148,7 @@ pub fn run( #[cfg(windows)] assert!(colored::control::set_virtual_terminal(true).is_ok()); - let log_level = LogLevel::from(&log_level_args); - set_up_logging(&log_level)?; + set_up_logging(global_options.log_level())?; if let Some(deprecated_alias_warning) = deprecated_alias_warning { warn_user!("{}", deprecated_alias_warning); @@ -181,38 +181,34 @@ pub fn run( Ok(ExitStatus::Success) } Command::Clean => { - commands::clean::clean(log_level)?; + commands::clean::clean(global_options.log_level())?; Ok(ExitStatus::Success) } Command::GenerateShellCompletion { shell } => { shell.generate(&mut Args::command(), &mut stdout()); Ok(ExitStatus::Success) } - Command::Check(args) => check(args, log_level), - Command::Format(args) => format(args, log_level), + Command::Check(args) => check(args, global_options), + Command::Format(args) => format(args, global_options), } } -fn format(args: FormatCommand, log_level: LogLevel) -> Result { - let (cli, config_arguments) = args.partition()?; +fn format(args: FormatCommand, global_options: GlobalConfigArgs) -> Result { + let (cli, config_arguments) = args.partition(global_options)?; if is_stdin(&cli.files, cli.stdin_filename.as_deref()) { commands::format_stdin::format_stdin(&cli, &config_arguments) } else { - commands::format::format(cli, &config_arguments, log_level) + commands::format::format(cli, &config_arguments) } } -pub fn check(args: CheckCommand, log_level: LogLevel) -> Result { - let (cli, config_arguments) = args.partition()?; +pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result { + let (cli, config_arguments) = args.partition(global_options)?; // 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_config = resolve::resolve( - cli.isolated, - &config_arguments, - cli.stdin_filename.as_deref(), - )?; + let pyproject_config = resolve::resolve(&config_arguments, cli.stdin_filename.as_deref())?; let mut writer: Box = match cli.output_file { Some(path) if !cli.watch => { @@ -303,7 +299,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result { } let modifications = commands::add_noqa::add_noqa(&files, &pyproject_config, &config_arguments)?; - if modifications > 0 && log_level >= LogLevel::Default { + if modifications > 0 && config_arguments.log_level >= LogLevel::Default { let s = if modifications == 1 { "" } else { "s" }; #[allow(clippy::print_stderr)] { @@ -315,7 +311,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result { let printer = Printer::new( output_format, - log_level, + config_arguments.log_level, fix_mode, unsafe_fixes, printer_flags, @@ -372,11 +368,8 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result { }; if matches!(change_kind, ChangeKind::Configuration) { - pyproject_config = resolve::resolve( - cli.isolated, - &config_arguments, - cli.stdin_filename.as_deref(), - )?; + pyproject_config = + resolve::resolve(&config_arguments, cli.stdin_filename.as_deref())?; } Printer::clear_screen()?; printer.write_to_user("File change detected...\n"); diff --git a/crates/ruff/src/resolve.rs b/crates/ruff/src/resolve.rs index a645583d08a2d..f1dbf5aa17ffd 100644 --- a/crates/ruff/src/resolve.rs +++ b/crates/ruff/src/resolve.rs @@ -16,12 +16,11 @@ use crate::args::ConfigArguments; /// Resolve the relevant settings strategy and defaults for the current /// invocation. pub fn resolve( - isolated: bool, config_arguments: &ConfigArguments, stdin_filename: Option<&Path>, ) -> Result { // First priority: if we're running in isolated mode, use the default settings. - if isolated { + if config_arguments.isolated { let config = config_arguments.transform(Configuration::default()); let settings = config.into_settings(&path_dedot::CWD)?; debug!("Isolated mode, not reading any pyproject.toml"); diff --git a/crates/ruff/tests/version.rs b/crates/ruff/tests/version.rs new file mode 100644 index 0000000000000..016feffd38472 --- /dev/null +++ b/crates/ruff/tests/version.rs @@ -0,0 +1,105 @@ +//! Tests for the --version command +use std::fs; +use std::process::Command; + +use anyhow::Result; +use insta_cmd::{assert_cmd_snapshot, get_cargo_bin}; +use tempfile::TempDir; + +const BIN_NAME: &str = "ruff"; +const VERSION_FILTER: [(&str, &str); 1] = [( + r"\d+\.\d+\.\d+(\+\d+)?( \(\w{9} \d\d\d\d-\d\d-\d\d\))?", + "[VERSION]", +)]; + +#[test] +fn version_basics() { + insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { + assert_cmd_snapshot!( + Command::new(get_cargo_bin(BIN_NAME)).arg("version"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + ruff [VERSION] + + ----- stderr ----- + "### + ); + }); +} + +/// `--config` is a global option, +/// so it's allowed to pass --config to subcommands such as `version` +/// -- the flag is simply ignored +#[test] +fn config_option_allowed_but_ignored() -> Result<()> { + let tempdir = TempDir::new()?; + let ruff_dot_toml = tempdir.path().join("ruff.toml"); + fs::File::create(&ruff_dot_toml)?; + insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { + assert_cmd_snapshot!( + Command::new(get_cargo_bin(BIN_NAME)) + .arg("version") + .arg("--config") + .arg(&ruff_dot_toml) + .args(["--config", "lint.isort.extra-standard-library = ['foo', 'bar']"]), @r###" + success: true + exit_code: 0 + ----- stdout ----- + ruff [VERSION] + + ----- stderr ----- + "### + ); + }); + Ok(()) +} +#[test] +fn config_option_ignored_but_validated() { + insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { + assert_cmd_snapshot!( + Command::new(get_cargo_bin(BIN_NAME)) + .arg("version") + .args(["--config", "foo = bar"]), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: invalid value 'foo = bar' for '--config ' + + tip: A `--config` flag must either be a path to a `.toml` configuration file + or a TOML ` = ` pair overriding a specific configuration + option + + The supplied argument is not valid TOML: + + TOML parse error at line 1, column 7 + | + 1 | foo = bar + | ^ + invalid string + expected `"`, `'` + + For more information, try '--help'. + "### + ); + }); +} + +/// `--isolated` is also a global option, +#[test] +fn isolated_option_allowed() { + insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { + assert_cmd_snapshot!( + Command::new(get_cargo_bin(BIN_NAME)).arg("version").arg("--isolated"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + ruff [VERSION] + + ----- stderr ----- + "### + ); + }); +} diff --git a/crates/ruff_dev/src/format_dev.rs b/crates/ruff_dev/src/format_dev.rs index b09f679bcf3bb..f54d080ffe542 100644 --- a/crates/ruff_dev/src/format_dev.rs +++ b/crates/ruff_dev/src/format_dev.rs @@ -27,7 +27,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::EnvFilter; -use ruff::args::{ConfigArguments, FormatArguments, FormatCommand, LogLevelArgs}; +use ruff::args::{ConfigArguments, FormatArguments, FormatCommand, GlobalConfigArgs, LogLevelArgs}; use ruff::resolve::resolve; use ruff_formatter::{FormatError, LineWidth, PrintError}; use ruff_linter::logging::LogLevel; @@ -43,7 +43,7 @@ fn parse_cli(dirs: &[PathBuf]) -> anyhow::Result<(FormatArguments, ConfigArgumen .no_binary_name(true) .get_matches_from(dirs); let arguments: FormatCommand = FormatCommand::from_arg_matches(&args_matches)?; - let (cli, config_arguments) = arguments.partition()?; + let (cli, config_arguments) = arguments.partition(GlobalConfigArgs::default())?; Ok((cli, config_arguments)) } @@ -52,11 +52,7 @@ fn find_pyproject_config( cli: &FormatArguments, config_arguments: &ConfigArguments, ) -> anyhow::Result { - let mut pyproject_config = resolve( - cli.isolated, - config_arguments, - cli.stdin_filename.as_deref(), - )?; + let mut pyproject_config = resolve(config_arguments, cli.stdin_filename.as_deref())?; // We don't want to format pyproject.toml pyproject_config.settings.file_resolver.include = FilePatternSet::try_from_iter([ FilePattern::Builtin("*.py"), diff --git a/crates/ruff_dev/src/main.rs b/crates/ruff_dev/src/main.rs index 1feef7394a3a3..83bf95f490289 100644 --- a/crates/ruff_dev/src/main.rs +++ b/crates/ruff_dev/src/main.rs @@ -4,8 +4,8 @@ use anyhow::Result; use clap::{Parser, Subcommand}; -use ruff::check; -use ruff_linter::logging::{set_up_logging, LogLevel}; +use ruff::{args::GlobalConfigArgs, check}; +use ruff_linter::logging::set_up_logging; use std::process::ExitCode; mod format_dev; @@ -28,6 +28,8 @@ const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../"); struct Args { #[command(subcommand)] command: Command, + #[clap(flatten)] + global_options: GlobalConfigArgs, } #[derive(Subcommand)] @@ -57,8 +59,6 @@ enum Command { Repeat { #[clap(flatten)] args: ruff::args::CheckCommand, - #[clap(flatten)] - log_level_args: ruff::args::LogLevelArgs, /// Run this many times #[clap(long)] repeat: usize, @@ -75,9 +75,12 @@ enum Command { } fn main() -> Result { - let args = Args::parse(); + let Args { + command, + global_options, + } = Args::parse(); #[allow(clippy::print_stdout)] - match args.command { + match command { Command::GenerateAll(args) => generate_all::main(&args)?, Command::GenerateJSONSchema(args) => generate_json_schema::main(&args)?, Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()), @@ -89,14 +92,12 @@ fn main() -> Result { Command::PrintTokens(args) => print_tokens::main(&args)?, Command::RoundTrip(args) => round_trip::main(&args)?, Command::Repeat { - args, + args: subcommand_args, repeat, - log_level_args, } => { - let log_level = LogLevel::from(&log_level_args); - set_up_logging(&log_level)?; + set_up_logging(global_options.log_level())?; for _ in 0..repeat { - check(args.clone(), log_level)?; + check(subcommand_args.clone(), global_options.clone())?; } } Command::FormatDev(args) => { diff --git a/crates/ruff_linter/src/logging.rs b/crates/ruff_linter/src/logging.rs index b97193a717bf5..2a64cde01c636 100644 --- a/crates/ruff_linter/src/logging.rs +++ b/crates/ruff_linter/src/logging.rs @@ -121,7 +121,7 @@ impl LogLevel { } } -pub fn set_up_logging(level: &LogLevel) -> Result<()> { +pub fn set_up_logging(level: LogLevel) -> Result<()> { fern::Dispatch::new() .format(|out, message, record| match record.level() { Level::Error => { diff --git a/docs/configuration.md b/docs/configuration.md index 769b0ecd8043e..35cea26b85d34 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -540,6 +540,17 @@ Log levels: -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) +Global options: + --config + Either a path to a TOML configuration file (`pyproject.toml` or + `ruff.toml`), or a TOML ` = ` pair (such as you might + find in a `ruff.toml` configuration file) overriding a specific + configuration option. Overrides of individual settings using this + option always take precedence over all configuration files, including + configuration files that were also specified using `--config` + --isolated + Ignore all configuration files + For help with a specific command, see: `ruff help `. ``` @@ -596,13 +607,6 @@ Options: --preview Enable preview mode; checks will include unstable rules and fixes. Use `--no-preview` to disable - --config - Either a path to a TOML configuration file (`pyproject.toml` or - `ruff.toml`), or a TOML ` = ` pair (such as you might - find in a `ruff.toml` configuration file) overriding a specific - configuration option. Overrides of individual settings using this - option always take precedence over all configuration files, including - configuration files that were also specified using `--config` --extension List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For example, to treat `.ipy` files as IPython @@ -658,8 +662,6 @@ File selection: Miscellaneous: -n, --no-cache Disable cache reads [env: RUFF_NO_CACHE=] - --isolated - Ignore all configuration files --cache-dir Path to the cache directory [env: RUFF_CACHE_DIR=] --stdin-filename @@ -675,6 +677,17 @@ Log levels: -q, --quiet Print diagnostics, but nothing else -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) + +Global options: + --config + Either a path to a TOML configuration file (`pyproject.toml` or + `ruff.toml`), or a TOML ` = ` pair (such as you might + find in a `ruff.toml` configuration file) overriding a specific + configuration option. Overrides of individual settings using this + option always take precedence over all configuration files, including + configuration files that were also specified using `--config` + --isolated + Ignore all configuration files ``` @@ -699,13 +712,6 @@ Options: Avoid writing any formatted files back; instead, exit with a non-zero status code and the difference between the current file and how the formatted file would look like - --config - Either a path to a TOML configuration file (`pyproject.toml` or - `ruff.toml`), or a TOML ` = ` pair (such as you might - find in a `ruff.toml` configuration file) overriding a specific - configuration option. Overrides of individual settings using this - option always take precedence over all configuration files, including - configuration files that were also specified using `--config` --extension List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For example, to treat `.ipy` files as IPython @@ -724,8 +730,6 @@ Miscellaneous: Disable cache reads [env: RUFF_NO_CACHE=] --cache-dir Path to the cache directory [env: RUFF_CACHE_DIR=] - --isolated - Ignore all configuration files --stdin-filename The name of the file when passing it through stdin @@ -755,6 +759,17 @@ Log levels: -q, --quiet Print diagnostics, but nothing else -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) + +Global options: + --config + Either a path to a TOML configuration file (`pyproject.toml` or + `ruff.toml`), or a TOML ` = ` pair (such as you might + find in a `ruff.toml` configuration file) overriding a specific + configuration option. Overrides of individual settings using this + option always take precedence over all configuration files, including + configuration files that were also specified using `--config` + --isolated + Ignore all configuration files ```