mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-13 13:57:22 +00:00

## Summary For formatter instabilities, the message we get look something like this: ```text Unstable formatting /home/konsti/ruff/target/checkouts/deepmodeling:dpdispatcher/dpdispatcher/slurm.py @@ -47,9 +47,9 @@ - script_header_dict["slurm_partition_line"] = ( - NOT_YET_IMPLEMENTED_ExprJoinedStr - ) + script_header_dict[ + "slurm_partition_line" + ] = NOT_YET_IMPLEMENTED_ExprJoinedStr Unstable formatting /home/konsti/ruff/target/checkouts/deepmodeling:dpdispatcher/dpdispatcher/pbs.py @@ -26,9 +26,9 @@ - pbs_script_header_dict["select_node_line"] += ( - NOT_YET_IMPLEMENTED_ExprJoinedStr - ) + pbs_script_header_dict[ + "select_node_line" + ] += NOT_YET_IMPLEMENTED_ExprJoinedStr ``` For ruff crashes. you don't even get that but just the file that crashed it. To extract the actual bug, you'd need to manually remove parts of the file, rerun to see if the bug still occurs (and revert if it doesn't) until you have a minimal example. With this script, you run ```shell cargo run --bin ruff_shrinking -- target/checkouts/deepmodeling:dpdispatcher/dpdispatcher/slurm.py target/minirepo/code.py "Unstable formatting" "target/debug/ruff_dev format-dev --stability-check target/minirepo" ``` and get ```python class Slurm(): def gen_script_header(self, job): if resources.queue_name != "": script_header_dict["slurm_partition_line"] = f"#SBATCH --partition {resources.queue_name}" ``` which is an nice minimal example. I've been using this script and it would be easier for me if this were part of main. The main disadvantage to merging is that it adds additional dependencies. ## Test Plan I've been using this for a number of minimization. This is an internal helper script you only run manually. I could add a test that minimizes a rule violation if required. --------- Co-authored-by: Micha Reiser <micha@reiser.io>
81 lines
2.2 KiB
Rust
81 lines
2.2 KiB
Rust
#![allow(clippy::print_stdout)]
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use anyhow::{bail, Context, Result};
|
|
use clap::{command, Parser, ValueEnum};
|
|
use rustpython_parser::lexer::lex;
|
|
use rustpython_parser::{parse_tokens, Mode};
|
|
|
|
use ruff_formatter::SourceCode;
|
|
use ruff_python_ast::source_code::CommentRangesBuilder;
|
|
|
|
use crate::{format_node, PyFormatOptions};
|
|
|
|
#[derive(ValueEnum, Clone, Debug)]
|
|
pub enum Emit {
|
|
/// Write back to the original files
|
|
Files,
|
|
/// Write to stdout
|
|
Stdout,
|
|
}
|
|
|
|
#[derive(Parser)]
|
|
#[command(author, version, about, long_about = None)]
|
|
pub struct Cli {
|
|
/// Python files to format. If there are none, stdin will be used. `-` as stdin is not supported
|
|
pub files: Vec<PathBuf>,
|
|
#[clap(long)]
|
|
pub emit: Option<Emit>,
|
|
/// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits with 1 and prints
|
|
/// a diff if formatting is required.
|
|
#[clap(long)]
|
|
pub check: bool,
|
|
#[clap(long)]
|
|
pub print_ir: bool,
|
|
#[clap(long)]
|
|
pub print_comments: bool,
|
|
}
|
|
|
|
pub fn format_and_debug_print(input: &str, cli: &Cli) -> Result<String> {
|
|
let mut tokens = Vec::new();
|
|
let mut comment_ranges = CommentRangesBuilder::default();
|
|
|
|
for result in lex(input, Mode::Module) {
|
|
let (token, range) = match result {
|
|
Ok((token, range)) => (token, range),
|
|
Err(err) => bail!("Source contains syntax errors {err:?}"),
|
|
};
|
|
|
|
comment_ranges.visit_token(&token, range);
|
|
tokens.push(Ok((token, range)));
|
|
}
|
|
|
|
let comment_ranges = comment_ranges.finish();
|
|
|
|
// Parse the AST.
|
|
let python_ast =
|
|
parse_tokens(tokens, Mode::Module, "<filename>").context("Syntax error in input")?;
|
|
|
|
let formatted = format_node(
|
|
&python_ast,
|
|
&comment_ranges,
|
|
input,
|
|
PyFormatOptions::default(),
|
|
)
|
|
.context("Failed to format node")?;
|
|
if cli.print_ir {
|
|
println!("{}", formatted.document().display(SourceCode::new(input)));
|
|
}
|
|
if cli.print_comments {
|
|
println!(
|
|
"{:#?}",
|
|
formatted.context().comments().debug(SourceCode::new(input))
|
|
);
|
|
}
|
|
Ok(formatted
|
|
.print()
|
|
.context("Failed to print the formatter IR")?
|
|
.as_code()
|
|
.to_string())
|
|
}
|