mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:53 +00:00
Reuse FormatResult
and FormatterIterationError
in format_stdin.rs
(#6985)
## Summary Ensures that we use the same error types and messages. Also renames those struct to `FormatCommand*` for consistency, and removes the `FormatCommandResult::Skipped` variant in favor of skipping in the iterator directly.
This commit is contained in:
parent
8d1610d960
commit
5de95d7054
2 changed files with 105 additions and 70 deletions
|
@ -61,19 +61,23 @@ pub(crate) fn format(
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let (results, errors): (Vec<_>, Vec<_>) = paths
|
let (results, errors): (Vec<_>, Vec<_>) = paths
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|entry| {
|
.filter_map(|entry| match entry {
|
||||||
let entry = entry?;
|
Ok(entry) => {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if let SourceType::Python(source_type @ (PySourceType::Python | PySourceType::Stub)) =
|
|
||||||
|
let SourceType::Python(source_type @ (PySourceType::Python | PySourceType::Stub)) =
|
||||||
SourceType::from(path)
|
SourceType::from(path)
|
||||||
{
|
else {
|
||||||
|
// Ignore any non-Python files.
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
let line_length = resolver.resolve(path, &pyproject_config).line_length;
|
let line_length = resolver.resolve(path, &pyproject_config).line_length;
|
||||||
let options = PyFormatOptions::from_source_type(source_type)
|
let options = PyFormatOptions::from_source_type(source_type)
|
||||||
.with_line_width(LineWidth::from(NonZeroU16::from(line_length)));
|
.with_line_width(LineWidth::from(NonZeroU16::from(line_length)));
|
||||||
format_path(path, options, mode)
|
Some(format_path(path, options, mode))
|
||||||
} else {
|
|
||||||
Ok(FormatResult::Skipped)
|
|
||||||
}
|
}
|
||||||
|
Err(err) => Some(Err(FormatCommandError::Ignore(err))),
|
||||||
})
|
})
|
||||||
.partition_map(|result| match result {
|
.partition_map(|result| match result {
|
||||||
Ok(diagnostic) => Left(diagnostic),
|
Ok(diagnostic) => Left(diagnostic),
|
||||||
|
@ -127,40 +131,39 @@ pub(crate) fn format(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format the file at the given [`Path`].
|
||||||
#[tracing::instrument(skip_all, fields(path = %path.display()))]
|
#[tracing::instrument(skip_all, fields(path = %path.display()))]
|
||||||
fn format_path(
|
fn format_path(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
options: PyFormatOptions,
|
options: PyFormatOptions,
|
||||||
mode: FormatMode,
|
mode: FormatMode,
|
||||||
) -> Result<FormatResult, FormatterIterationError> {
|
) -> Result<FormatCommandResult, FormatCommandError> {
|
||||||
let unformatted = std::fs::read_to_string(path)
|
let unformatted = std::fs::read_to_string(path)
|
||||||
.map_err(|err| FormatterIterationError::Read(path.to_path_buf(), err))?;
|
.map_err(|err| FormatCommandError::Read(Some(path.to_path_buf()), err))?;
|
||||||
let formatted = {
|
let formatted = {
|
||||||
let span = span!(Level::TRACE, "format_path_without_io", path = %path.display());
|
let span = span!(Level::TRACE, "format_path_without_io", path = %path.display());
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
format_module(&unformatted, options)
|
format_module(&unformatted, options)
|
||||||
.map_err(|err| FormatterIterationError::FormatModule(path.to_path_buf(), err))?
|
.map_err(|err| FormatCommandError::FormatModule(Some(path.to_path_buf()), err))?
|
||||||
};
|
};
|
||||||
let formatted = formatted.as_code();
|
let formatted = formatted.as_code();
|
||||||
if formatted.len() == unformatted.len() && formatted == unformatted {
|
if formatted.len() == unformatted.len() && formatted == unformatted {
|
||||||
Ok(FormatResult::Unchanged)
|
Ok(FormatCommandResult::Unchanged)
|
||||||
} else {
|
} else {
|
||||||
if mode.is_write() {
|
if mode.is_write() {
|
||||||
std::fs::write(path, formatted.as_bytes())
|
std::fs::write(path, formatted.as_bytes())
|
||||||
.map_err(|err| FormatterIterationError::Write(path.to_path_buf(), err))?;
|
.map_err(|err| FormatCommandError::Write(Some(path.to_path_buf()), err))?;
|
||||||
}
|
}
|
||||||
Ok(FormatResult::Formatted)
|
Ok(FormatCommandResult::Formatted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, is_macro::Is)]
|
||||||
enum FormatResult {
|
pub(crate) enum FormatCommandResult {
|
||||||
/// The file was formatted.
|
/// The file was formatted.
|
||||||
Formatted,
|
Formatted,
|
||||||
/// The file was unchanged, as the formatted contents matched the existing contents.
|
/// The file was unchanged, as the formatted contents matched the existing contents.
|
||||||
Unchanged,
|
Unchanged,
|
||||||
/// The file was skipped, as it was not a Python file.
|
|
||||||
Skipped,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -171,23 +174,19 @@ struct FormatResultSummary {
|
||||||
formatted: usize,
|
formatted: usize,
|
||||||
/// The number of files that were unchanged.
|
/// The number of files that were unchanged.
|
||||||
unchanged: usize,
|
unchanged: usize,
|
||||||
/// The number of files that were skipped.
|
|
||||||
skipped: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormatResultSummary {
|
impl FormatResultSummary {
|
||||||
fn new(diagnostics: Vec<FormatResult>, mode: FormatMode) -> Self {
|
fn new(diagnostics: Vec<FormatCommandResult>, mode: FormatMode) -> Self {
|
||||||
let mut summary = Self {
|
let mut summary = Self {
|
||||||
mode,
|
mode,
|
||||||
formatted: 0,
|
formatted: 0,
|
||||||
unchanged: 0,
|
unchanged: 0,
|
||||||
skipped: 0,
|
|
||||||
};
|
};
|
||||||
for diagnostic in diagnostics {
|
for diagnostic in diagnostics {
|
||||||
match diagnostic {
|
match diagnostic {
|
||||||
FormatResult::Formatted => summary.formatted += 1,
|
FormatCommandResult::Formatted => summary.formatted += 1,
|
||||||
FormatResult::Unchanged => summary.unchanged += 1,
|
FormatCommandResult::Unchanged => summary.unchanged += 1,
|
||||||
FormatResult::Skipped => summary.skipped += 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
summary
|
summary
|
||||||
|
@ -235,14 +234,14 @@ impl Display for FormatResultSummary {
|
||||||
|
|
||||||
/// An error that can occur while formatting a set of files.
|
/// An error that can occur while formatting a set of files.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
enum FormatterIterationError {
|
pub(crate) enum FormatCommandError {
|
||||||
Ignore(#[from] ignore::Error),
|
Ignore(#[from] ignore::Error),
|
||||||
Read(PathBuf, io::Error),
|
Read(Option<PathBuf>, io::Error),
|
||||||
Write(PathBuf, io::Error),
|
Write(Option<PathBuf>, io::Error),
|
||||||
FormatModule(PathBuf, FormatModuleError),
|
FormatModule(Option<PathBuf>, FormatModuleError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FormatterIterationError {
|
impl Display for FormatCommandError {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Ignore(err) => {
|
Self::Ignore(err) => {
|
||||||
|
@ -267,6 +266,7 @@ impl Display for FormatterIterationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Read(path, err) => {
|
Self::Read(path, err) => {
|
||||||
|
if let Some(path) = path {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}{}{} {err}",
|
"{}{}{} {err}",
|
||||||
|
@ -274,8 +274,12 @@ impl Display for FormatterIterationError {
|
||||||
fs::relativize_path(path).bold(),
|
fs::relativize_path(path).bold(),
|
||||||
":".bold()
|
":".bold()
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}{} {err}", "Failed to read".bold(), ":".bold())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Self::Write(path, err) => {
|
Self::Write(path, err) => {
|
||||||
|
if let Some(path) = path {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}{}{} {err}",
|
"{}{}{} {err}",
|
||||||
|
@ -283,8 +287,12 @@ impl Display for FormatterIterationError {
|
||||||
fs::relativize_path(path).bold(),
|
fs::relativize_path(path).bold(),
|
||||||
":".bold()
|
":".bold()
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}{} {err}", "Failed to write".bold(), ":".bold())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Self::FormatModule(path, err) => {
|
Self::FormatModule(path, err) => {
|
||||||
|
if let Some(path) = path {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}{}{} {err}",
|
"{}{}{} {err}",
|
||||||
|
@ -292,6 +300,9 @@ impl Display for FormatterIterationError {
|
||||||
fs::relativize_path(path).bold(),
|
fs::relativize_path(path).bold(),
|
||||||
":".bold()
|
":".bold()
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}{} {err}", "Failed to format".bold(), ":".bold())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use log::warn;
|
||||||
|
|
||||||
use ruff_python_formatter::{format_module, PyFormatOptions};
|
use ruff_python_formatter::{format_module, PyFormatOptions};
|
||||||
use ruff_workspace::resolver::python_file_at_path;
|
use ruff_workspace::resolver::python_file_at_path;
|
||||||
|
|
||||||
use crate::args::{FormatArguments, Overrides};
|
use crate::args::{FormatArguments, Overrides};
|
||||||
use crate::commands::format::FormatMode;
|
use crate::commands::format::{FormatCommandError, FormatCommandResult, FormatMode};
|
||||||
use crate::resolve::resolve;
|
use crate::resolve::resolve;
|
||||||
use crate::stdin::read_from_stdin;
|
use crate::stdin::read_from_stdin;
|
||||||
use crate::ExitStatus;
|
use crate::ExitStatus;
|
||||||
|
@ -32,26 +34,48 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &Overrides) -> Resu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the file.
|
// Format the file.
|
||||||
let unformatted = read_from_stdin()?;
|
let path = cli.stdin_filename.as_deref();
|
||||||
let options = cli
|
let options = path
|
||||||
.stdin_filename
|
|
||||||
.as_deref()
|
|
||||||
.map(PyFormatOptions::from_extension)
|
.map(PyFormatOptions::from_extension)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let formatted = format_module(&unformatted, options)?;
|
match format_source(path, options, mode) {
|
||||||
|
Ok(result) => match mode {
|
||||||
match mode {
|
FormatMode::Write => Ok(ExitStatus::Success),
|
||||||
FormatMode::Write => {
|
|
||||||
stdout().lock().write_all(formatted.as_code().as_bytes())?;
|
|
||||||
Ok(ExitStatus::Success)
|
|
||||||
}
|
|
||||||
FormatMode::Check => {
|
FormatMode::Check => {
|
||||||
if formatted.as_code().len() == unformatted.len() && formatted.as_code() == unformatted
|
if result.is_formatted() {
|
||||||
{
|
|
||||||
Ok(ExitStatus::Success)
|
|
||||||
} else {
|
|
||||||
Ok(ExitStatus::Failure)
|
Ok(ExitStatus::Failure)
|
||||||
|
} else {
|
||||||
|
Ok(ExitStatus::Success)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
warn!("{err}");
|
||||||
|
Ok(ExitStatus::Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format source code read from `stdin`.
|
||||||
|
fn format_source(
|
||||||
|
path: Option<&Path>,
|
||||||
|
options: PyFormatOptions,
|
||||||
|
mode: FormatMode,
|
||||||
|
) -> Result<FormatCommandResult, FormatCommandError> {
|
||||||
|
let unformatted = read_from_stdin()
|
||||||
|
.map_err(|err| FormatCommandError::Read(path.map(Path::to_path_buf), err))?;
|
||||||
|
let formatted = format_module(&unformatted, options)
|
||||||
|
.map_err(|err| FormatCommandError::FormatModule(path.map(Path::to_path_buf), err))?;
|
||||||
|
let formatted = formatted.as_code();
|
||||||
|
if formatted.len() == unformatted.len() && formatted == unformatted {
|
||||||
|
Ok(FormatCommandResult::Unchanged)
|
||||||
|
} else {
|
||||||
|
if mode.is_write() {
|
||||||
|
stdout()
|
||||||
|
.lock()
|
||||||
|
.write_all(formatted.as_bytes())
|
||||||
|
.map_err(|err| FormatCommandError::Write(path.map(Path::to_path_buf), err))?;
|
||||||
|
}
|
||||||
|
Ok(FormatCommandResult::Formatted)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue