mirror of https://github.com/astral-sh/ruff
[ty] Exit with `2` if there's any IO error (#21508)
Co-authored-by: David Peter <mail@david-peter.de>
This commit is contained in:
parent
c796a70ec9
commit
663f78e644
|
|
@ -67,7 +67,7 @@ jobs:
|
|||
|
||||
cd ..
|
||||
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@0aff03414da5d242e97a9f43fb502e085637a4a1"
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@e5c5f5b2d762af91b28490537fe0077334165693"
|
||||
|
||||
ecosystem-analyzer \
|
||||
--repository ruff \
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ jobs:
|
|||
|
||||
cd ..
|
||||
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@0aff03414da5d242e97a9f43fb502e085637a4a1"
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@e5c5f5b2d762af91b28490537fe0077334165693"
|
||||
|
||||
ecosystem-analyzer \
|
||||
--verbose \
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ mod python_version;
|
|||
mod version;
|
||||
|
||||
pub use args::Cli;
|
||||
use ty_project::metadata::settings::TerminalSettings;
|
||||
use ty_static::EnvVars;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
|
@ -21,7 +22,9 @@ use clap::{CommandFactory, Parser};
|
|||
use colored::Colorize;
|
||||
use crossbeam::channel as crossbeam_channel;
|
||||
use rayon::ThreadPoolBuilder;
|
||||
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, DisplayDiagnostics, Severity};
|
||||
use ruff_db::diagnostic::{
|
||||
Diagnostic, DiagnosticId, DisplayDiagnosticConfig, DisplayDiagnostics, Severity,
|
||||
};
|
||||
use ruff_db::files::File;
|
||||
use ruff_db::max_parallelism;
|
||||
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
|
||||
|
|
@ -193,6 +196,12 @@ pub enum ExitStatus {
|
|||
InternalError = 101,
|
||||
}
|
||||
|
||||
impl ExitStatus {
|
||||
pub const fn is_internal_error(self) -> bool {
|
||||
matches!(self, ExitStatus::InternalError)
|
||||
}
|
||||
}
|
||||
|
||||
impl Termination for ExitStatus {
|
||||
fn report(self) -> ExitCode {
|
||||
ExitCode::from(self as u8)
|
||||
|
|
@ -334,11 +343,8 @@ impl MainLoop {
|
|||
let diagnostics_count = result.len();
|
||||
|
||||
let mut stdout = self.printer.stream_for_details().lock();
|
||||
let max_severity = result
|
||||
.iter()
|
||||
.map(Diagnostic::severity)
|
||||
.max()
|
||||
.unwrap_or(Severity::Info);
|
||||
let exit_status =
|
||||
exit_status_from_diagnostics(&result, terminal_settings);
|
||||
|
||||
// Only render diagnostics if they're going to be displayed, since doing
|
||||
// so is expensive.
|
||||
|
|
@ -359,25 +365,14 @@ impl MainLoop {
|
|||
)?;
|
||||
}
|
||||
|
||||
if max_severity.is_fatal() {
|
||||
if exit_status.is_internal_error() {
|
||||
tracing::warn!(
|
||||
"A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details."
|
||||
);
|
||||
}
|
||||
|
||||
if self.watcher.is_none() {
|
||||
return Ok(match max_severity {
|
||||
Severity::Info => ExitStatus::Success,
|
||||
Severity::Warning => {
|
||||
if terminal_settings.error_on_warning {
|
||||
ExitStatus::Failure
|
||||
} else {
|
||||
ExitStatus::Success
|
||||
}
|
||||
}
|
||||
Severity::Error => ExitStatus::Failure,
|
||||
Severity::Fatal => ExitStatus::InternalError,
|
||||
});
|
||||
return Ok(exit_status);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -410,6 +405,40 @@ impl MainLoop {
|
|||
}
|
||||
}
|
||||
|
||||
fn exit_status_from_diagnostics(
|
||||
diagnostics: &[Diagnostic],
|
||||
terminal_settings: &TerminalSettings,
|
||||
) -> ExitStatus {
|
||||
if diagnostics.is_empty() {
|
||||
return ExitStatus::Success;
|
||||
}
|
||||
|
||||
let mut max_severity = Severity::Info;
|
||||
let mut io_error = false;
|
||||
|
||||
for diagnostic in diagnostics {
|
||||
max_severity = max_severity.max(diagnostic.severity());
|
||||
io_error = io_error || matches!(diagnostic.id(), DiagnosticId::Io);
|
||||
}
|
||||
|
||||
if !max_severity.is_fatal() && io_error {
|
||||
return ExitStatus::Error;
|
||||
}
|
||||
|
||||
match max_severity {
|
||||
Severity::Info => ExitStatus::Success,
|
||||
Severity::Warning => {
|
||||
if terminal_settings.error_on_warning {
|
||||
ExitStatus::Failure
|
||||
} else {
|
||||
ExitStatus::Success
|
||||
}
|
||||
}
|
||||
Severity::Error => ExitStatus::Failure,
|
||||
Severity::Fatal => ExitStatus::InternalError,
|
||||
}
|
||||
}
|
||||
|
||||
/// A progress reporter for `ty check`.
|
||||
struct IndicatifReporter {
|
||||
collector: CollectReporter,
|
||||
|
|
|
|||
|
|
@ -562,9 +562,9 @@ fn check_non_existing_path() -> anyhow::Result<()> {
|
|||
|
||||
assert_cmd_snapshot!(
|
||||
case.command().arg("project/main.py").arg("project/tests"),
|
||||
@r###"
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
error[io]: `<temp_dir>/project/main.py`: No such file or directory (os error 2)
|
||||
|
||||
|
|
@ -574,7 +574,7 @@ fn check_non_existing_path() -> anyhow::Result<()> {
|
|||
|
||||
----- stderr -----
|
||||
WARN No python files found under the given path(s)
|
||||
"###
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ cd ..
|
|||
echo "Project selector: ${PRIMER_SELECTOR}"
|
||||
# Allow the exit code to be 0 or 1, only fail for actual mypy_primer crashes/bugs
|
||||
uvx \
|
||||
--from="git+https://github.com/hauntsaninja/mypy_primer@ab5d30e2d4ecdaf7d6cc89395c7130143d6d3c82" \
|
||||
--from="git+https://github.com/hauntsaninja/mypy_primer@089ac1da83cf26aee9c98de412b7eb10e20b2212" \
|
||||
mypy_primer \
|
||||
--repo ruff \
|
||||
--type-checker ty \
|
||||
|
|
|
|||
Loading…
Reference in New Issue