Python: refactor ExecService to get rid of ProcessOutput and better support interactive execution.

1. `ProcessOutput` is a legacy thing with some redundant flags: replaced with modern `EelProcessExecutionResult`.

2. There was a bug in `ProcessInteractiveHandler`: one could fetch all data from stdout, and we then did that again to get a result. That leads to an empty result. It is now fixed, see `executeInteractive` doc.

GitOrigin-RevId: 7fa57f8110a202a32a3531ff6507d42a270075a3
This commit is contained in:
Ilya.Kazakevich
2025-05-09 00:16:46 +02:00
committed by intellij-monorepo-bot
parent 067fef4544
commit 11c31cfde7
14 changed files with 200 additions and 73 deletions

View File

@@ -4,6 +4,10 @@ package com.jetbrains.python.errorProcessing
import com.intellij.execution.process.ProcessOutput
import com.intellij.openapi.util.NlsContexts
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResult
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResultInfo
import com.intellij.platform.eel.provider.utils.stderrString
import com.intellij.platform.eel.provider.utils.stdoutString
import com.jetbrains.python.PyCommunityBundle
import org.jetbrains.annotations.Nls
@@ -15,7 +19,7 @@ class ExecError(
/**
* I.e ['-v']
*/
val args: Array<String>,
val args: Array<out String>,
val errorReason: ExecErrorReason,
/**
@@ -37,8 +41,9 @@ sealed interface ExecErrorReason {
/**
* A process started but failed with an error.
* [processOutput] contains exit code, stdout etc
*/
data class UnexpectedProcessTermination(val exitCode: Int, val stdout: String, val stderr: String) : ExecErrorReason
data class UnexpectedProcessTermination(private val processOutput: EelProcessExecutionResult) : ExecErrorReason, EelProcessExecutionResultInfo by processOutput
/**
* Process started, but killed due to timeout without returning any useful data
@@ -47,11 +52,11 @@ sealed interface ExecErrorReason {
}
fun ProcessOutput.asExecutionFailed(): ExecErrorReason.UnexpectedProcessTermination =
ExecErrorReason.UnexpectedProcessTermination(exitCode, stdout, stderr)
ExecErrorReason.UnexpectedProcessTermination(EelProcessExecutionResult(exitCode, stdout.encodeToByteArray(), stderr.encodeToByteArray()))
private fun getExecErrorMessage(
exec: String,
args: Array<String>,
args: Array<out String>,
additionalMessage: @NlsContexts.DialogTitle String?,
execErrorReason: ExecErrorReason,
): @Nls String {
@@ -68,8 +73,8 @@ private fun getExecErrorMessage(
PyCommunityBundle.message("python.execution.error",
additionalMessage ?: "",
commandLine,
r.stdout,
r.stderr,
r.stdoutString,
r.stderrString,
r.exitCode)
}