mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:37 +00:00
Make --quiet more aggressive (#566)
This commit is contained in:
parent
9f9cbb5520
commit
a3f7de2257
4 changed files with 135 additions and 65 deletions
14
src/cli.rs
14
src/cli.rs
|
@ -7,6 +7,7 @@ use log::warn;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::checks_gen::CheckCodePrefix;
|
use crate::checks_gen::CheckCodePrefix;
|
||||||
|
use crate::logging::LogLevel;
|
||||||
use crate::printer::SerializationFormat;
|
use crate::printer::SerializationFormat;
|
||||||
use crate::settings::configuration::Configuration;
|
use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::types::{PatternPrefixPair, PythonVersion};
|
use crate::settings::types::{PatternPrefixPair, PythonVersion};
|
||||||
|
@ -93,6 +94,19 @@ pub struct Cli {
|
||||||
pub stdin_filename: Option<String>,
|
pub stdin_filename: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Map the CLI settings to a `LogLevel`.
|
||||||
|
pub fn extract_log_level(cli: &Cli) -> LogLevel {
|
||||||
|
if cli.silent {
|
||||||
|
LogLevel::Silent
|
||||||
|
} else if cli.quiet {
|
||||||
|
LogLevel::Quiet
|
||||||
|
} else if cli.verbose {
|
||||||
|
LogLevel::Verbose
|
||||||
|
} else {
|
||||||
|
LogLevel::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Warnable {
|
pub enum Warnable {
|
||||||
Select,
|
Select,
|
||||||
ExtendSelect,
|
ExtendSelect,
|
||||||
|
|
|
@ -15,7 +15,36 @@ macro_rules! tell_user {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_up_logging(verbose: bool) -> Result<()> {
|
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
|
pub enum LogLevel {
|
||||||
|
// No output (+ `log::LevelFilter::Off`).
|
||||||
|
Silent,
|
||||||
|
// Only show lint violations, with no decorative output (+ `log::LevelFilter::Off`).
|
||||||
|
Quiet,
|
||||||
|
// All user-facing output (+ `log::LevelFilter::Info`).
|
||||||
|
Default,
|
||||||
|
// All user-facing output (+ `log::LevelFilter::Debug`).
|
||||||
|
Verbose,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogLevel {
|
||||||
|
fn level_filter(&self) -> log::LevelFilter {
|
||||||
|
match self {
|
||||||
|
LogLevel::Default => log::LevelFilter::Info,
|
||||||
|
LogLevel::Verbose => log::LevelFilter::Debug,
|
||||||
|
LogLevel::Quiet => log::LevelFilter::Off,
|
||||||
|
LogLevel::Silent => log::LevelFilter::Off,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LogLevel {
|
||||||
|
fn default() -> Self {
|
||||||
|
LogLevel::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_up_logging(level: &LogLevel) -> Result<()> {
|
||||||
fern::Dispatch::new()
|
fern::Dispatch::new()
|
||||||
.format(|out, message, record| {
|
.format(|out, message, record| {
|
||||||
out.finish(format_args!(
|
out.finish(format_args!(
|
||||||
|
@ -26,12 +55,22 @@ pub fn set_up_logging(verbose: bool) -> Result<()> {
|
||||||
message
|
message
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.level(if verbose {
|
.level(level.level_filter())
|
||||||
log::LevelFilter::Debug
|
|
||||||
} else {
|
|
||||||
log::LevelFilter::Info
|
|
||||||
})
|
|
||||||
.chain(std::io::stdout())
|
.chain(std::io::stdout())
|
||||||
.apply()
|
.apply()
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::logging::LogLevel;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ordering() {
|
||||||
|
assert!(LogLevel::Default > LogLevel::Silent);
|
||||||
|
assert!(LogLevel::Default >= LogLevel::Default);
|
||||||
|
assert!(LogLevel::Quiet > LogLevel::Silent);
|
||||||
|
assert!(LogLevel::Verbose > LogLevel::Default);
|
||||||
|
assert!(LogLevel::Verbose > LogLevel::Silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -16,17 +16,16 @@ use rayon::prelude::*;
|
||||||
use ruff::cache;
|
use ruff::cache;
|
||||||
use ruff::checks::{CheckCode, CheckKind};
|
use ruff::checks::{CheckCode, CheckKind};
|
||||||
use ruff::checks_gen::CheckCodePrefix;
|
use ruff::checks_gen::CheckCodePrefix;
|
||||||
use ruff::cli::{collect_per_file_ignores, warn_on, Cli, Warnable};
|
use ruff::cli::{collect_per_file_ignores, extract_log_level, warn_on, Cli, Warnable};
|
||||||
use ruff::fs::iter_python_files;
|
use ruff::fs::iter_python_files;
|
||||||
use ruff::linter::{add_noqa_to_path, autoformat_path, lint_path, lint_stdin};
|
use ruff::linter::{add_noqa_to_path, autoformat_path, lint_path, lint_stdin};
|
||||||
use ruff::logging::set_up_logging;
|
use ruff::logging::{set_up_logging, LogLevel};
|
||||||
use ruff::message::Message;
|
use ruff::message::Message;
|
||||||
use ruff::printer::{Printer, SerializationFormat};
|
use ruff::printer::{Printer, SerializationFormat};
|
||||||
use ruff::settings::configuration::Configuration;
|
use ruff::settings::configuration::Configuration;
|
||||||
use ruff::settings::types::FilePattern;
|
use ruff::settings::types::FilePattern;
|
||||||
use ruff::settings::user::UserConfiguration;
|
use ruff::settings::user::UserConfiguration;
|
||||||
use ruff::settings::{pyproject, Settings};
|
use ruff::settings::{pyproject, Settings};
|
||||||
use ruff::tell_user;
|
|
||||||
use walkdir::DirEntry;
|
use walkdir::DirEntry;
|
||||||
|
|
||||||
#[cfg(feature = "update-informer")]
|
#[cfg(feature = "update-informer")]
|
||||||
|
@ -223,10 +222,10 @@ fn autoformat(files: &[PathBuf], settings: &Settings) -> Result<usize> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner_main() -> Result<ExitCode> {
|
fn inner_main() -> Result<ExitCode> {
|
||||||
let mut cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
cli.quiet |= cli.silent;
|
|
||||||
|
|
||||||
set_up_logging(cli.verbose)?;
|
let log_level = extract_log_level(&cli);
|
||||||
|
set_up_logging(&log_level)?;
|
||||||
|
|
||||||
// Find the project root and pyproject.toml.
|
// Find the project root and pyproject.toml.
|
||||||
let project_root = pyproject::find_project_root(&cli.files);
|
let project_root = pyproject::find_project_root(&cli.files);
|
||||||
|
@ -320,7 +319,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
cache::init()?;
|
cache::init()?;
|
||||||
|
|
||||||
let mut printer = Printer::new(cli.format, cli.verbose);
|
let printer = Printer::new(&cli.format, &log_level);
|
||||||
if cli.watch {
|
if cli.watch {
|
||||||
if cli.fix {
|
if cli.fix {
|
||||||
eprintln!("Warning: --fix is not enabled in watch mode.");
|
eprintln!("Warning: --fix is not enabled in watch mode.");
|
||||||
|
@ -340,12 +339,10 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
|
|
||||||
// Perform an initial run instantly.
|
// Perform an initial run instantly.
|
||||||
printer.clear_screen()?;
|
printer.clear_screen()?;
|
||||||
tell_user!("Starting linter in watch mode...\n");
|
printer.write_to_user("Starting linter in watch mode...\n");
|
||||||
|
|
||||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
||||||
if !cli.silent {
|
printer.write_continuously(&messages)?;
|
||||||
printer.write_continuously(&messages)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the file watcher.
|
// Configure the file watcher.
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
@ -360,12 +357,10 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
if let Some(path) = e.path {
|
if let Some(path) = e.path {
|
||||||
if path.to_string_lossy().ends_with(".py") {
|
if path.to_string_lossy().ends_with(".py") {
|
||||||
printer.clear_screen()?;
|
printer.clear_screen()?;
|
||||||
tell_user!("File change detected...\n");
|
printer.write_to_user("File change detected...\n");
|
||||||
|
|
||||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
||||||
if !cli.silent {
|
printer.write_continuously(&messages)?;
|
||||||
printer.write_continuously(&messages)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,37 +369,36 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
}
|
}
|
||||||
} else if cli.add_noqa {
|
} else if cli.add_noqa {
|
||||||
let modifications = add_noqa(&cli.files, &settings)?;
|
let modifications = add_noqa(&cli.files, &settings)?;
|
||||||
if modifications > 0 {
|
if modifications > 0 && log_level >= LogLevel::Default {
|
||||||
println!("Added {modifications} noqa directives.");
|
println!("Added {modifications} noqa directives.");
|
||||||
}
|
}
|
||||||
} else if cli.autoformat {
|
} else if cli.autoformat {
|
||||||
let modifications = autoformat(&cli.files, &settings)?;
|
let modifications = autoformat(&cli.files, &settings)?;
|
||||||
if modifications > 0 {
|
if modifications > 0 && log_level >= LogLevel::Default {
|
||||||
println!("Formatted {modifications} files.");
|
println!("Formatted {modifications} files.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (messages, should_print_messages, should_check_updates) =
|
let is_stdin = cli.files == vec![PathBuf::from("-")];
|
||||||
if cli.files == vec![PathBuf::from("-")] {
|
|
||||||
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
|
// Generate lint violations.
|
||||||
let path = Path::new(&filename);
|
let messages = if is_stdin {
|
||||||
(
|
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
|
||||||
run_once_stdin(&settings, path, cli.fix)?,
|
let path = Path::new(&filename);
|
||||||
!cli.silent && !cli.fix,
|
run_once_stdin(&settings, path, cli.fix)?
|
||||||
false,
|
} else {
|
||||||
)
|
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?
|
||||||
} else {
|
};
|
||||||
(
|
|
||||||
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?,
|
// Always try to print violations (the printer itself may suppress output),
|
||||||
!cli.silent,
|
// unless we're writing fixes via stdin (in which case, the transformed
|
||||||
!cli.quiet,
|
// source code goes to stdout).
|
||||||
)
|
if !(is_stdin && cli.fix) {
|
||||||
};
|
|
||||||
if should_print_messages {
|
|
||||||
printer.write_once(&messages)?;
|
printer.write_once(&messages)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for updates if we're in a non-silent log level.
|
||||||
#[cfg(feature = "update-informer")]
|
#[cfg(feature = "update-informer")]
|
||||||
if should_check_updates {
|
if !is_stdin && log_level >= LogLevel::Default {
|
||||||
check_for_updates();
|
check_for_updates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ use rustpython_parser::ast::Location;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::checks::{CheckCode, CheckKind};
|
use crate::checks::{CheckCode, CheckKind};
|
||||||
|
use crate::logging::LogLevel;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::tell_user;
|
use crate::tell_user;
|
||||||
|
|
||||||
|
@ -25,17 +26,27 @@ struct ExpandedMessage<'a> {
|
||||||
filename: &'a String,
|
filename: &'a String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Printer {
|
pub struct Printer<'a> {
|
||||||
format: SerializationFormat,
|
format: &'a SerializationFormat,
|
||||||
verbose: bool,
|
log_level: &'a LogLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Printer {
|
impl<'a> Printer<'a> {
|
||||||
pub fn new(format: SerializationFormat, verbose: bool) -> Self {
|
pub fn new(format: &'a SerializationFormat, log_level: &'a LogLevel) -> Self {
|
||||||
Self { format, verbose }
|
Self { format, log_level }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_once(&mut self, messages: &[Message]) -> Result<()> {
|
pub fn write_to_user(&self, message: &str) {
|
||||||
|
if self.log_level >= &LogLevel::Default {
|
||||||
|
tell_user!("{}", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_once(&self, messages: &[Message]) -> Result<()> {
|
||||||
|
if matches!(self.log_level, LogLevel::Silent) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let (fixed, outstanding): (Vec<&Message>, Vec<&Message>) =
|
let (fixed, outstanding): (Vec<&Message>, Vec<&Message>) =
|
||||||
messages.iter().partition(|message| message.fixed);
|
messages.iter().partition(|message| message.fixed);
|
||||||
let num_fixable = outstanding
|
let num_fixable = outstanding
|
||||||
|
@ -64,22 +75,26 @@ impl Printer {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SerializationFormat::Text => {
|
SerializationFormat::Text => {
|
||||||
if !fixed.is_empty() {
|
if self.log_level >= &LogLevel::Default {
|
||||||
println!(
|
if !fixed.is_empty() {
|
||||||
"Found {} error(s) ({} fixed).",
|
println!(
|
||||||
outstanding.len(),
|
"Found {} error(s) ({} fixed).",
|
||||||
fixed.len()
|
outstanding.len(),
|
||||||
)
|
fixed.len()
|
||||||
} else if !outstanding.is_empty() || self.verbose {
|
)
|
||||||
println!("Found {} error(s).", outstanding.len())
|
} else if !outstanding.is_empty() {
|
||||||
|
println!("Found {} error(s).", outstanding.len())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for message in outstanding {
|
for message in outstanding {
|
||||||
println!("{}", message)
|
println!("{}", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
if num_fixable > 0 {
|
if self.log_level >= &LogLevel::Default {
|
||||||
println!("{num_fixable} potentially fixable with the --fix option.")
|
if num_fixable > 0 {
|
||||||
|
println!("{num_fixable} potentially fixable with the --fix option.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,14 +102,22 @@ impl Printer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_continuously(&mut self, messages: &[Message]) -> Result<()> {
|
pub fn write_continuously(&self, messages: &[Message]) -> Result<()> {
|
||||||
tell_user!(
|
if matches!(self.log_level, LogLevel::Silent) {
|
||||||
"Found {} error(s). Watching for file changes.",
|
return Ok(());
|
||||||
messages.len(),
|
}
|
||||||
);
|
|
||||||
|
if self.log_level >= &LogLevel::Default {
|
||||||
|
tell_user!(
|
||||||
|
"Found {} error(s). Watching for file changes.",
|
||||||
|
messages.len(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if !messages.is_empty() {
|
if !messages.is_empty() {
|
||||||
println!();
|
if self.log_level >= &LogLevel::Default {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
for message in messages {
|
for message in messages {
|
||||||
println!("{}", message)
|
println!("{}", message)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +126,7 @@ impl Printer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_screen(&mut self) -> Result<()> {
|
pub fn clear_screen(&self) -> Result<()> {
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
clearscreen::clear()?;
|
clearscreen::clear()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue