-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add prototype of
ruff format
for projects
**Summary** Add recursive formatting based on `ruff check` file discovery for `ruff format`, as a prototype for the formatter alpha. This allows e.g. `format ../projects/django/`. It's still lacking support for any settings except line length. Error handling works in my manual tests: ``` $ target/debug/ruff format scripts/ warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only. ``` (the above changes `add_rule.py` where we have the wrong bin op breaking) ``` $ ruff format ../projects/django/ warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only. Failed to format /home/konsti/projects/django/tests/test_runner_apps/tagged/tests_syntax_error.py: source contains syntax errors: ParseError { error: UnrecognizedToken(Name { name: "syntax_error" }, None), offset: 131, source_path: "<filename>" } ``` ``` $ target/debug/ruff format a warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only. Failed to read /home/konsti/ruff/a/d.py: Permission denied (os error 13) ``` **Test Plan** Missing! I'm not sure if it's worth building tests at this stage or how they should look like.
- Loading branch information
Showing
7 changed files
with
135 additions
and
16 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#![allow(clippy::print_stderr)] | ||
|
||
use crate::args::{Arguments, Overrides}; | ||
use crate::resolve::resolve; | ||
use crate::ExitStatus; | ||
use anyhow::bail; | ||
use colored::Colorize; | ||
use rayon::iter::{IntoParallelIterator, ParallelIterator}; | ||
use ruff::resolver::python_files_in_path; | ||
use ruff_formatter::LineWidth; | ||
use ruff_python_ast::PySourceType; | ||
use ruff_python_formatter::{format_module, FormatModuleError, PyFormatOptions}; | ||
use std::io; | ||
use std::path::{Path, PathBuf}; | ||
use thiserror::Error; | ||
use tracing::span; | ||
use tracing::Level; | ||
|
||
/// The inner errors are all flat, i.e. none of them has a source | ||
#[derive(Error, Debug)] | ||
enum FormatterIterationError { | ||
#[error("Failed to traverse the inputs paths: {0}")] | ||
Ignore(#[from] ignore::Error), | ||
#[error("Failed to read {0}: {1}")] | ||
Read(PathBuf, io::Error), | ||
#[error("Failed to write {0}: {1}")] | ||
Write(PathBuf, io::Error), | ||
#[error("Failed to format {0}: {1}")] | ||
FormatModule(PathBuf, FormatModuleError), | ||
} | ||
|
||
pub(crate) fn format(cli: &Arguments, overrides: &Overrides) -> anyhow::Result<ExitStatus> { | ||
let pyproject_config = resolve( | ||
cli.isolated, | ||
cli.config.as_deref(), | ||
overrides, | ||
cli.stdin_filename.as_deref(), | ||
)?; | ||
let (paths, resolver) = python_files_in_path(&cli.files, &pyproject_config, overrides)?; | ||
if paths.is_empty() { | ||
bail!("no python files in TODO(@konstin) pass them in") | ||
} | ||
|
||
let all_success = paths | ||
.into_par_iter() | ||
.map(|dir_entry| { | ||
let dir_entry = dir_entry?; | ||
let path = dir_entry.path(); | ||
let source_type = PySourceType::from(path); | ||
if !(source_type.is_python() || source_type.is_stub()) | ||
|| path | ||
.extension() | ||
.is_some_and(|extension| extension == "toml") | ||
{ | ||
return Ok(()); | ||
} | ||
|
||
let line_length = resolver.resolve(path, &pyproject_config).line_length; | ||
// TODO(@konstin): Unify `LineWidth` and `LineLength` | ||
let line_width = LineWidth::try_from( | ||
u16::try_from(line_length.get()).expect("Line shouldn't be larger than 2**16"), | ||
) | ||
.expect("Configured line length is too large for the formatter"); | ||
let options = PyFormatOptions::from_extension(path).with_line_width(line_width); | ||
|
||
format_path(path, options) | ||
}) | ||
.map(|result| { | ||
match result { | ||
Ok(()) => true, | ||
Err(err) => { | ||
// The inner errors are all flat, i.e. none of them has a source | ||
eprintln!("{}", err.to_string().red().bold()); | ||
false | ||
} | ||
} | ||
}) | ||
.all(|success| success); | ||
|
||
if all_success { | ||
Ok(ExitStatus::Success) | ||
} else { | ||
Ok(ExitStatus::Error) | ||
} | ||
} | ||
|
||
#[tracing::instrument(skip_all, fields(path = %path.display()))] | ||
fn format_path(path: &Path, options: PyFormatOptions) -> Result<(), FormatterIterationError> { | ||
let unformatted = std::fs::read_to_string(path) | ||
.map_err(|err| FormatterIterationError::Read(path.to_path_buf(), err))?; | ||
let formatted = { | ||
let span = span!(Level::TRACE, "format_path_without_io", path = %path.display()); | ||
let _enter = span.enter(); | ||
format_module(&unformatted, options) | ||
.map_err(|err| FormatterIterationError::FormatModule(path.to_path_buf(), err))? | ||
}; | ||
std::fs::write(path, formatted.as_code().as_bytes()) | ||
.map_err(|err| FormatterIterationError::Write(path.to_path_buf(), err))?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters