Add fix option to pyproject.toml (#639)

This commit is contained in:
Charlie Marsh 2022-11-07 09:46:21 -05:00 committed by GitHub
parent 7773e9728b
commit 07c9fc55f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 13 deletions

View file

@ -38,8 +38,10 @@ pub struct Cli {
#[arg(short, long)]
pub watch: bool,
/// Attempt to automatically fix lint errors.
#[arg(short, long)]
pub fix: bool,
#[arg(long, overrides_with("no_fix"))]
fix: bool,
#[clap(long, overrides_with("fix"), hide = true)]
no_fix: bool,
/// Disable cache reads.
#[arg(short, long)]
pub no_cache: bool,
@ -94,6 +96,22 @@ pub struct Cli {
pub stdin_filename: Option<String>,
}
impl Cli {
// See: https://github.com/clap-rs/clap/issues/3146
pub fn fix(&self) -> Option<bool> {
resolve_bool_arg(self.fix, self.no_fix)
}
}
fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
match (yes, no) {
(true, false) => Some(true),
(false, true) => Some(false),
(false, false) => None,
(..) => unreachable!("Clap should make this impossible"),
}
}
/// Map the CLI settings to a `LogLevel`.
pub fn extract_log_level(cli: &Cli) -> LogLevel {
if cli.silent {
@ -165,7 +183,7 @@ pub fn warn_on(
}
}
/// Collect a list of `PatternPrefixPair` structs as a `BTreeMap`.
/// Convert a list of `PatternPrefixPair` structs to `PerFileIgnore`.
pub fn collect_per_file_ignores(
pairs: Vec<PatternPrefixPair>,
project_root: &Option<PathBuf>,

View file

@ -220,7 +220,9 @@ fn autoformat(files: &[PathBuf], settings: &Settings) -> Result<usize> {
}
fn inner_main() -> Result<ExitCode> {
// Extract command-line arguments.
let cli = Cli::parse();
let fix = cli.fix();
let log_level = extract_log_level(&cli);
set_up_logging(&log_level)?;
@ -239,7 +241,7 @@ fn inner_main() -> Result<ExitCode> {
None => debug!("Unable to find pyproject.toml; using default settings..."),
};
// Parse the settings from the pyproject.toml and command-line arguments.
// Reconcile configuration from pyproject.toml and command-line arguments.
let exclude: Vec<FilePattern> = cli
.exclude
.iter()
@ -296,6 +298,9 @@ fn inner_main() -> Result<ExitCode> {
if let Some(dummy_variable_rgx) = cli.dummy_variable_rgx {
configuration.dummy_variable_rgx = dummy_variable_rgx;
}
if let Some(fix) = fix {
configuration.fix = fix;
}
if cli.show_settings && cli.show_files {
eprintln!("Error: specify --show-settings or show-files (not both).");
@ -306,6 +311,8 @@ fn inner_main() -> Result<ExitCode> {
return Ok(ExitCode::SUCCESS);
}
// Extract settings for internal use.
let autofix = configuration.fix;
let settings = Settings::from_configuration(configuration);
if cli.show_files {
@ -318,7 +325,7 @@ fn inner_main() -> Result<ExitCode> {
let printer = Printer::new(&cli.format, &log_level);
if cli.watch {
if cli.fix {
if autofix {
eprintln!("Warning: --fix is not enabled in watch mode.");
}
@ -381,15 +388,15 @@ fn inner_main() -> Result<ExitCode> {
let messages = if is_stdin {
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
let path = Path::new(&filename);
run_once_stdin(&settings, path, cli.fix)?
run_once_stdin(&settings, path, autofix)?
} else {
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?
run_once(&cli.files, &settings, !cli.no_cache, autofix)?
};
// Always try to print violations (the printer itself may suppress output),
// unless we're writing fixes via stdin (in which case, the transformed
// source code goes to stdout).
if !(is_stdin && cli.fix) {
if !(is_stdin && autofix) {
printer.write_once(&messages)?;
}

View file

@ -20,6 +20,7 @@ pub struct Configuration {
pub extend_exclude: Vec<FilePattern>,
pub extend_ignore: Vec<CheckCodePrefix>,
pub extend_select: Vec<CheckCodePrefix>,
pub fix: bool,
pub ignore: Vec<CheckCodePrefix>,
pub line_length: usize,
pub per_file_ignores: Vec<PerFileIgnore>,
@ -91,6 +92,7 @@ impl Configuration {
.select
.unwrap_or_else(|| vec![CheckCodePrefix::E, CheckCodePrefix::F]),
extend_select: options.extend_select.unwrap_or_default(),
fix: options.fix.unwrap_or_default(),
ignore: options.ignore.unwrap_or_default(),
line_length: options.line_length.unwrap_or(88),
per_file_ignores: options

View file

@ -11,15 +11,16 @@ use crate::{flake8_annotations, flake8_quotes, pep8_naming};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct Options {
pub line_length: Option<usize>,
pub dummy_variable_rgx: Option<String>,
pub exclude: Option<Vec<String>>,
pub extend_exclude: Option<Vec<String>>,
pub select: Option<Vec<CheckCodePrefix>>,
pub extend_select: Option<Vec<CheckCodePrefix>>,
pub ignore: Option<Vec<CheckCodePrefix>>,
pub extend_ignore: Option<Vec<CheckCodePrefix>>,
pub extend_select: Option<Vec<CheckCodePrefix>>,
pub fix: Option<bool>,
pub ignore: Option<Vec<CheckCodePrefix>>,
pub line_length: Option<usize>,
pub per_file_ignores: Option<BTreeMap<String, Vec<CheckCodePrefix>>>,
pub dummy_variable_rgx: Option<String>,
pub select: Option<Vec<CheckCodePrefix>>,
pub target_version: Option<PythonVersion>,
// Plugins
pub flake8_annotations: Option<flake8_annotations::settings::Options>,

View file

@ -134,6 +134,7 @@ mod tests {
Some(Tools {
ruff: Some(Options {
line_length: None,
fix: None,
exclude: None,
extend_exclude: None,
select: None,
@ -162,6 +163,7 @@ line-length = 79
Some(Tools {
ruff: Some(Options {
line_length: Some(79),
fix: None,
exclude: None,
extend_exclude: None,
select: None,
@ -190,6 +192,7 @@ exclude = ["foo.py"]
Some(Tools {
ruff: Some(Options {
line_length: None,
fix: None,
exclude: Some(vec!["foo.py".to_string()]),
extend_exclude: None,
select: None,
@ -218,6 +221,7 @@ select = ["E501"]
Some(Tools {
ruff: Some(Options {
line_length: None,
fix: None,
exclude: None,
extend_exclude: None,
select: Some(vec![CheckCodePrefix::E501]),
@ -247,6 +251,7 @@ ignore = ["E501"]
Some(Tools {
ruff: Some(Options {
line_length: None,
fix: None,
exclude: None,
extend_exclude: None,
select: None,
@ -315,6 +320,7 @@ other-attribute = 1
config,
Options {
line_length: Some(88),
fix: None,
exclude: None,
extend_exclude: Some(vec![
"excluded.py".to_string(),

View file

@ -40,6 +40,7 @@ pub struct UserConfiguration {
pub extend_exclude: Vec<Exclusion>,
pub extend_ignore: Vec<CheckCodePrefix>,
pub extend_select: Vec<CheckCodePrefix>,
pub fix: bool,
pub ignore: Vec<CheckCodePrefix>,
pub line_length: usize,
pub per_file_ignores: Vec<(Exclusion, Vec<CheckCode>)>,
@ -74,6 +75,7 @@ impl UserConfiguration {
.collect(),
extend_ignore: configuration.extend_ignore,
extend_select: configuration.extend_select,
fix: configuration.fix,
ignore: configuration.ignore,
line_length: configuration.line_length,
per_file_ignores: configuration